diff options
| author | Adam Soltys <[email protected]> | 2024-11-07 21:16:25 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2024-11-08 09:27:40 -0800 |
| commit | 32fcc461cd43c8907df5e306d520bb671307eab1 (patch) | |
| tree | 0253780c569998b6c1a5f43026586e94916c3fee /src/routes | |
| parent | be5aa52cea1d57c875cfb22d25c6a866b8de2239 (diff) | |
| download | coinos-ui-32fcc461cd43c8907df5e306d520bb671307eab1.tar.gz coinos-ui-32fcc461cd43c8907df5e306d520bb671307eab1.zip | |
svelte 5
Diffstat (limited to 'src/routes')
69 files changed, 884 insertions, 639 deletions
diff --git a/src/routes/(app)/+error.svelte b/src/routes/(app)/+error.svelte index 6ce7979c..b950608b 100644 --- a/src/routes/(app)/+error.svelte +++ b/src/routes/(app)/+error.svelte @@ -3,7 +3,7 @@ import Icon from "$comp/Icon.svelte"; import { page } from "$app/stores"; - export let data; + let { data } = $props(); let { user } = data; let link = user ? `/${user.username}` : "/"; diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 095e597d..c09fc309 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { SvelteToast } from "@zerodevx/svelte-toast"; import { onDestroy, onMount } from "svelte"; import { close, connect, send } from "$lib/socket"; @@ -22,12 +24,10 @@ import { t, locale, loading } from "$lib/translations"; import { goto, afterNavigate, preloadData } from "$app/navigation"; - export let data; + let { data, children } = $props(); - let { generate, rate, user, subject, token, rates, theme } = data; - $: theme = $themeStore; + let { generate, rate, user, subject, token, rates, theme } = $state(data); - $: update(data); let update = (data) => { ({ rate, user, subject, token, rates, theme } = data); }; @@ -67,7 +67,6 @@ } }); - $: browser && connect(token); let lost, checkTimer, @@ -93,6 +92,15 @@ clearTimeout(expireTimer); } }); + run(() => { + theme = $themeStore; + }); + run(() => { + update(data); + }); + run(() => { + browser && connect(token); + }); </script> {#if browser && user && $passwordPrompt} @@ -119,7 +127,7 @@ <main class="pb-20 min-h-dvh" data-theme={theme}> <AppHeader {user} {subject} /> {#if !$loading} - <slot /> + {@render children?.()} {/if} </main> diff --git a/src/routes/(app)/[username]/(profile)/+layout.svelte b/src/routes/(app)/[username]/(profile)/+layout.svelte index 03cad4ff..65911eee 100644 --- a/src/routes/(app)/[username]/(profile)/+layout.svelte +++ b/src/routes/(app)/[username]/(profile)/+layout.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { invalidate } from "$app/navigation"; import { browser } from "$app/environment"; import { hexToUint8Array } from "uint8array-extras"; @@ -8,7 +10,7 @@ import { bech32m } from "@scure/base"; import { page } from "$app/stores"; - export let data; + let { data, children } = $props(); let { encode, toWords } = bech32m; @@ -22,10 +24,9 @@ follows, followers, followList, - } = data; - let { currency, npub, username: n, display } = subject; + } = $state(data); + let { currency, npub, username: n, display } = $state(subject); - $: refresh(data); let refresh = (data) => { ({ events, @@ -41,15 +42,8 @@ ({ currency, npub, username: n, display } = subject); }; - $: stripped = n.replace(/\s/g, ""); - $: username = n.length > 60 ? n.substr(0, 6) : display || stripped; - $: lnaddr = subject?.anon - ? subject.lud16 || undefined - : `${stripped}@${$page.url.host}`; - $: profile = `${$page.url.host}/${subject.anon ? npub : stripped}`; - let list = []; - $: followList.then((l) => (list = l)); + let list = $state([]); let follow = async () => { list = [...list, subject.pubkey]; let tags = await get( @@ -95,15 +89,14 @@ } }; - $: following = list.some((t) => t.includes(subject.pubkey)); - let showBio; + let showBio = $state(); let toggleBio = () => (showBio = !showBio); - let showDetails; + let showDetails = $state(); let toggleDetails = () => (showDetails = !showDetails); - let password; + let password = $state(); let reset = async () => { try { @@ -113,28 +106,41 @@ fail(e.message); } }; + run(() => { + refresh(data); + }); + let stripped = $derived(n.replace(/\s/g, "")); + let username = $derived(n.length > 60 ? n.substr(0, 6) : display || stripped); + let lnaddr = $derived(subject?.anon + ? subject.lud16 || undefined + : `${stripped}@${$page.url.host}`); + let profile = $derived(`${$page.url.host}/${subject.anon ? npub : stripped}`); + run(() => { + followList.then((l) => (list = l)); + }); + let following = $derived(list.some((t) => t.includes(subject.pubkey))); </script> <div class="container mx-auto w-full px-4 flex flex-wrap lg:flex-nowrap"> - <div class="hidden lg:block lg:w-[280px] xl:w-[360px]" /> + <div class="hidden lg:block lg:w-[280px] xl:w-[360px]"></div> <div class="w-full lg:w-[280px] xl:w-[360px] lg:absolute space-y-2 left-20 mx-auto" > <button type="button" - on:click={toggleDetails} + onclick={toggleDetails} class="flex text-3xl font-bold text-center mx-auto justify-center gap-2" > <div class="my-auto break-words">{display || username}</div> - <iconify-icon icon="ph:qr-code-bold" width="32" /> + <iconify-icon icon="ph:qr-code-bold" width="32"></iconify-icon> </button> {#if subject.address || subject.about} <div class="text-secondary mx-auto text-center lg:mx-0 break-words space-y-1" class:line-clamp-2={!showBio} - on:click={toggleBio} - on:keydown={toggleBio} + onclick={toggleBio} + onkeydown={toggleBio} > <div> {subject.address || subject.about} @@ -177,11 +183,11 @@ {lnaddr} </div> <div class="flex mb-auto gap-1"> - <button class="my-auto" on:click={() => copy(lnaddr)} - ><iconify-icon icon="ph:copy-bold" width="32" /></button + <button class="my-auto" onclick={() => copy(lnaddr)} + ><iconify-icon icon="ph:copy-bold" width="32"></iconify-icon></button > <a href={`/qr/${encodeURIComponent(lnaddr)}`} class="my-auto"> - <iconify-icon icon="ph:qr-code-bold" width="32" /> + <iconify-icon icon="ph:qr-code-bold" width="32"></iconify-icon> </a> </div> </div> @@ -194,8 +200,8 @@ {profile} </div> <div class="flex mb-auto gap-1"> - <button class="my-auto" on:click={() => copy(profile)} - ><iconify-icon icon="ph:copy-bold" width="32" /></button + <button class="my-auto" onclick={() => copy(profile)} + ><iconify-icon icon="ph:copy-bold" width="32"></iconify-icon></button > <a href={`/qr/${encodeURIComponent( @@ -203,7 +209,7 @@ )}`} class="my-auto" > - <iconify-icon icon="ph:qr-code-bold" width="32" /> + <iconify-icon icon="ph:qr-code-bold" width="32"></iconify-icon> </a> </div> </div> @@ -215,11 +221,11 @@ {npub} </div> <div class="flex my-auto gap-1"> - <button class="my-auto" on:click={() => copy(npub)} - ><iconify-icon icon="ph:copy-bold" width="32" /></button + <button class="my-auto" onclick={() => copy(npub)} + ><iconify-icon icon="ph:copy-bold" width="32"></iconify-icon></button > <a href={`/qr/${encodeURIComponent(npub)}`} class="my-auto"> - <iconify-icon icon="ph:qr-code-bold" width="32" /> + <iconify-icon icon="ph:qr-code-bold" width="32"></iconify-icon> </a> </div> </div> @@ -230,13 +236,13 @@ <div class="flex flex-wrap gap-2 w-full text-lg"> {#if user && user.username !== subject.username && subject.pubkey} {#if following} - <button class="btn" on:click={unfollow}> - <iconify-icon icon="ph:user-bold" width="32" /> + <button class="btn" onclick={unfollow}> + <iconify-icon icon="ph:user-bold" width="32"></iconify-icon> <div class="my-auto">{$t("user.unfollow")}</div> </button> {:else} - <button class="btn" on:click={follow}> - <iconify-icon icon="ph:user-bold" width="32" /> + <button class="btn" onclick={follow}> + <iconify-icon icon="ph:user-bold" width="32"></iconify-icon> <div class="my-auto">{$t("user.follow")}</div> </button> {/if} @@ -256,14 +262,14 @@ <!-- {/if} --> {#if user?.admin && user.username !== subject.username} - <form class="w-full flex" on:submit|preventDefault={reset}> + <form class="w-full flex" onsubmit={preventDefault(reset)}> <input placeholder="Password reset" bind:value={password} /> <button type="submit" class="rounded-2xl border py-5 px-6 font-bold hover:opacity-80 flex w-60" > <div class="mx-auto flex"> - <iconify-icon icon="ph:clock" width="32" /> + <iconify-icon icon="ph:clock" width="32"></iconify-icon> </div> </button> </form> @@ -275,7 +281,7 @@ <div class="mx-auto space-y-5 lg:max-w-xl xl:max-w-2xl lg:pl-10 mt-5 lg:mt-0" > - <slot /> + {@render children?.()} </div> </div> </div> diff --git a/src/routes/(app)/[username]/(profile)/+page.svelte b/src/routes/(app)/[username]/(profile)/+page.svelte index d14f2f58..e956aab7 100644 --- a/src/routes/(app)/[username]/(profile)/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { btc, f, sat } from "$lib/utils"; import Icon from "$comp/Icon.svelte"; import Account from "$comp/Account.svelte"; @@ -8,20 +10,22 @@ import { installPrompt } from "$lib/store"; import { afterNavigate, preloadData } from "$app/navigation"; - export let data; + let { data } = $props(); afterNavigate(() => { preloadData(`/${user.username}/receive`); preloadData("/send"); }); - let { accounts, subject, user, items, rates } = data; - $: ({ currency } = subject); - $: rate = rates[currency]; - $: total = items.reduce((a, b) => a + b.price * b.quantity, 0); + let { accounts, subject, user, items, rates } = $state(data); + let { currency } = $derived(subject); + let rate = $derived(rates[currency]); + let total = $derived(items.reduce((a, b) => a + b.price * b.quantity, 0)); let refresh = (d) => ({ accounts, items, subject, user, rates } = d); - $: refresh(data); + run(() => { + refresh(data); + }); let install = async () => { if (!$installPrompt) return; @@ -42,14 +46,14 @@ <a href={`/account/savings`} class="contents"> <button class="btn btn-lg w-full rounded-2xl whitespace-nowrap"> - <iconify-icon icon="ph:plus-circle-bold" width="32" /> + <iconify-icon icon="ph:plus-circle-bold" width="32"></iconify-icon> {$t("accounts.addAccount")} </button> </a> {#if $installPrompt} - <button class="btn btn-accent lg:hidden" on:click={install}> - <iconify-icon icon="ph:floppy-disk-bold" width="32" /> + <button class="btn btn-accent lg:hidden" onclick={install}> + <iconify-icon icon="ph:floppy-disk-bold" width="32"></iconify-icon> {$t("user.install")} </button> {/if} @@ -64,7 +68,7 @@ {#if total > 0} <button class="rounded-2xl py-5 px-6 font-bold hover:bg-neutral-700 flex bg-black text-white mx-auto" - on:click={checkout} + onclick={checkout} > <div class="mx-auto flex"> <div class="my-auto text-2xl"> diff --git a/src/routes/(app)/[username]/(profile)/event/[id]/+page.svelte b/src/routes/(app)/[username]/(profile)/event/[id]/+page.svelte index 74ce1067..9244d392 100644 --- a/src/routes/(app)/[username]/(profile)/event/[id]/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/event/[id]/+page.svelte @@ -1,6 +1,6 @@ <script> import Event from "$comp/Event.svelte"; - export let data; + let { data } = $props(); let { event } = data; </script> diff --git a/src/routes/(app)/[username]/(profile)/followers/+page.svelte b/src/routes/(app)/[username]/(profile)/followers/+page.svelte index c0080990..b7ad4948 100644 --- a/src/routes/(app)/[username]/(profile)/followers/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/followers/+page.svelte @@ -4,7 +4,7 @@ import { browser } from "$app/environment"; import VirtualScroll from "svelte-virtual-scroll-list"; - export let data; + let { data } = $props(); let { followers } = data; </script> @@ -17,34 +17,36 @@ <div>Loading followers...</div> {:then followers} {#if followers.length} - <VirtualScroll data={followers} key="pubkey" let:data pageMode={true}> - <a - href={`/${data.pubkey}`} - data-sveltekit-preload-data="tap" - rel="nofollow" - > - <div - class="flex border-b last:border-b-0 py-4 text-2xl text-secondary" - :key={data.pubkey} + <VirtualScroll data={followers} key="pubkey" pageMode={true}> + {#snippet children({ data })} + <a + href={`/${data.pubkey}`} + data-sveltekit-preload-data="tap" + rel="nofollow" > - <div class="mb-auto mr-2"> - <div class="md:hidden"> - <Avatar size={12} user={data} disabled={true} /> + <div + class="flex border-b last:border-b-0 py-4 text-2xl text-secondary" + :key={data.pubkey} + > + <div class="mb-auto mr-2"> + <div class="md:hidden"> + <Avatar size={12} user={data} disabled={true} /> + </div> + <div class="hidden md:block"> + <Avatar size={20} user={data} disabled={true} /> + </div> </div> - <div class="hidden md:block"> - <Avatar size={20} user={data} disabled={true} /> - </div> - </div> - <div class="w-full flex pb-1 text-black my-auto"> - <div> - <div>{data.display_name || ""}</div> - <div class="text-secondary text-lg">@{data.name}</div> + <div class="w-full flex pb-1 text-black my-auto"> + <div> + <div>{data.display_name || ""}</div> + <div class="text-secondary text-lg">@{data.name}</div> + </div> </div> </div> - </div> - </a> - </VirtualScroll> + </a> + {/snippet} + </VirtualScroll> {:else} <div>No followers</div> {/if} diff --git a/src/routes/(app)/[username]/(profile)/follows/+page.svelte b/src/routes/(app)/[username]/(profile)/follows/+page.svelte index 9b2f70d1..ad416500 100644 --- a/src/routes/(app)/[username]/(profile)/follows/+page.svelte +++ b/src/routes/(app)/[username]/(profile)/follows/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { onMount } from "svelte"; import { t } from "$lib/translations"; import Avatar from "$comp/Avatar.svelte"; @@ -6,10 +8,12 @@ import VirtualScroll from "svelte-virtual-scroll-list"; import { invalidate } from "$app/navigation"; - export let data; - let { follows } = data; - $: refresh(data); + let { data } = $props(); + let { follows } = $state(data); let refresh = (data) => ({ follows } = data); + run(() => { + refresh(data); + }); </script> <div class="px-3 md:px-0 w-full md:w-[400px] mx-auto"> @@ -22,31 +26,33 @@ {:then follows} {#if follows.length} {#if browser} - <VirtualScroll data={follows} key="pubkey" let:data pageMode={true}> - <a - href={`/${data.pubkey}`} - data-sveltekit-preload-data="tap" - rel="nofollow" - > - <div class="flex py-4 text-lg text-secondary" :key={data.pubkey}> - <div class="mb-auto mr-2"> - <div class="md:hidden"> - <Avatar size={12} user={data} disabled={true} /> - </div> - <div class="hidden md:block"> - <Avatar size={20} user={data} disabled={true} /> + <VirtualScroll data={follows} key="pubkey" pageMode={true}> + {#snippet children({ data })} + <a + href={`/${data.pubkey}`} + data-sveltekit-preload-data="tap" + rel="nofollow" + > + <div class="flex py-4 text-lg text-secondary" :key={data.pubkey}> + <div class="mb-auto mr-2"> + <div class="md:hidden"> + <Avatar size={12} user={data} disabled={true} /> + </div> + <div class="hidden md:block"> + <Avatar size={20} user={data} disabled={true} /> + </div> </div> - </div> - <div class="w-full flex pb-1 text-black my-auto"> - <div> - <div>{data.display_name || ""}</div> - <div class="text-secondary text-base">@{data.name}</div> + <div class="w-full flex pb-1 text-black my-auto"> + <div> + <div>{data.display_name || ""}</div> + <div class="text-secondary text-base">@{data.name}</div> + </div> </div> </div> - </div> - </a> - </VirtualScroll> + </a> + {/snippet} + </VirtualScroll> {/if} {:else} <div>No follows</div> diff --git a/src/routes/(app)/[username]/+layout.svelte b/src/routes/(app)/[username]/+layout.svelte index ce152831..e3ad7259 100644 --- a/src/routes/(app)/[username]/+layout.svelte +++ b/src/routes/(app)/[username]/+layout.svelte @@ -1,9 +1,9 @@ <script> - export let data; + let { data, children, fixed } = $props(); </script> <div class="content"> - <slot /> + {@render children?.()} </div> -<slot name="fixed" /> +{@render fixed?.()} diff --git a/src/routes/(app)/[username]/receive/+page.svelte b/src/routes/(app)/[username]/receive/+page.svelte index e9e5ca43..9a696929 100644 --- a/src/routes/(app)/[username]/receive/+page.svelte +++ b/src/routes/(app)/[username]/receive/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { send } from "$lib/socket"; import { btc, post, copy, f, get, types, sat, s, sats } from "$lib/utils"; import { tick, onMount, onDestroy } from "svelte"; @@ -12,12 +14,11 @@ import { t } from "$lib/translations"; import { goto, invalidate } from "$app/navigation"; - export let data; + let { data } = $props(); let showOptions; - let { id, rates, subject, user, src, text } = data; - $: refresh(data); + let { id, rates, subject, user, src, text } = $state(data); let refresh = (data) => { ({ id, rates, subject, user, src, text } = data); }; @@ -29,19 +30,15 @@ let qr; - $: link = [types.bitcoin, types.liquid].includes(type) - ? text - : `lightning:${text}`; - $: txt = [types.bitcoin, types.liquid].includes(type) ? hash : text; let aid = subject.id; - let invoice = { + let invoice = $state({ aid, type: types.lightning, items: [], user: subject, - }; - let amount, amountFiat, tip; + }); + let amount = $state(), amountFiat, tip; let setType = async (type) => { invoice.type = type; @@ -75,10 +72,16 @@ }; let newAmount; - let settingAmount; + let settingAmount = $state(); let toggleAmount = () => (settingAmount = !settingAmount); - let fiat; let submit; + run(() => { + refresh(data); + }); + let link = $derived([types.bitcoin, types.liquid].includes(type) + ? text + : `lightning:${text}`); + let txt = $derived([types.bitcoin, types.liquid].includes(type) ? hash : text); </script> <div class="invoice container mx-auto max-w-xl px-4 space-y-2"> @@ -115,7 +118,6 @@ <SetAmount {currency} {rate} - {fiat} {submit} {settingAmount} {setAmount} diff --git a/src/routes/(app)/account/[id]/+page.svelte b/src/routes/(app)/account/[id]/+page.svelte index be7d6112..29add530 100644 --- a/src/routes/(app)/account/[id]/+page.svelte +++ b/src/routes/(app)/account/[id]/+page.svelte @@ -14,19 +14,19 @@ PUBLIC_COINOS_RELAY as relay, } from "$env/static/public"; - export let data; + let { data } = $props(); let { account, user } = data; let { id, name, seed } = account; - let mnemonic, password; - let passwordPrompt; - let cancel = () => (passwordPrompt = false); + let mnemonic = $state(), password = $state(); + let passwordPrompt = $state(); + let cancel = $state(() => (passwordPrompt = false)); let toggle = () => (passwordPrompt = !passwordPrompt); - let submit = async () => { + let submit = $state(async () => { toggle(); let entropy = await decrypt(seed, password); mnemonic = entropyToMnemonic(entropy, wordlist); - }; + }); let del = async () => { try { @@ -37,7 +37,7 @@ } }; - let nwc; + let nwc = $state(); let revealNwc = () => (nwc = `nostr+walletconnect://${pk}?relay=${encodeURIComponent( relay, @@ -53,17 +53,17 @@ {#if mnemonic} <Mnemonic {mnemonic} /> - <button on:click={() => copy(mnemonic)} type="button" class="btn"> - <iconify-icon icon="ph:copy-bold" width="32" /> + <button onclick={() => copy(mnemonic)} type="button" class="btn"> + <iconify-icon icon="ph:copy-bold" width="32"></iconify-icon> <div class="my-auto">{$t("accounts.copy")}</div></button > {:else if seed} <button - on:click={toggle} + onclick={toggle} type="button" class="flex gap-2 rounded-2xl border py-5 mx-auto px-6 w-full justify-center" > - <iconify-icon icon="ph:eye-bold" width="32" /> + <iconify-icon icon="ph:eye-bold" width="32"></iconify-icon> <div class="my-auto">{$t("accounts.revealMnemonic")}</div></button > {:else if nwc} @@ -71,26 +71,26 @@ {nwc} </div> <button - on:click={() => copy(nwc)} + onclick={() => copy(nwc)} type="button" class="flex gap-2 rounded-2xl border py-5 mx-auto px-6 w-full justify-center" > - <iconify-icon icon="ph:copy-bold" width="32" /> + <iconify-icon icon="ph:copy-bold" width="32"></iconify-icon> <div class="my-auto">{$t("accounts.copy")}</div></button > <a href={`/qr/${encodeURIComponent(nwc)}`} class="my-auto block"> <button - on:click={() => copy(nwc)} + onclick={() => copy(nwc)} type="button" class="flex gap-2 rounded-2xl border py-5 mx-auto px-6 w-full justify-center" > - <iconify-icon icon="ph:qr-code-bold" width="32" /> + <iconify-icon icon="ph:qr-code-bold" width="32"></iconify-icon> <div class="my-auto">{$t("user.receive.showQR")}</div></button > </a> {:else} <button - on:click={revealNwc} + onclick={revealNwc} type="button" class="flex gap-2 rounded-2xl border py-5 mx-auto px-6 w-full justify-center" > @@ -101,7 +101,7 @@ {#if seed} <button - on:click={del} + onclick={del} type="button" class="flex gap-2 rounded-2xl border py-5 mx-auto px-6 w-full justify-center" > @@ -111,7 +111,7 @@ {/if} </div> - <div /> + <div></div> </form> </div> </div> diff --git a/src/routes/(app)/account/import/+page.svelte b/src/routes/(app)/account/import/+page.svelte index a1d6549b..b94cc839 100644 --- a/src/routes/(app)/account/import/+page.svelte +++ b/src/routes/(app)/account/import/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { goto } from "$app/navigation"; import { mnemonic } from "$lib/store"; import { fail, focus, versions } from "$lib/utils"; @@ -8,7 +10,7 @@ import { validateMnemonic } from "@scure/bip39"; import { wordlist } from "@scure/bip39/wordlists/english"; - let el, pasted, text; + let el = $state(), pasted = $state(), text = $state(); let paste = async () => { text = await navigator.clipboard.readText(); @@ -26,14 +28,16 @@ } }; - $: if (browser && pasted && text) form.submit() && (pasted = false); + run(() => { + if (browser && pasted && text) form.submit() && (pasted = false); + }); </script> <div class="space-y-5"> <h1 class="text-center text-3xl font-semibold">{$t("accounts.import")}</h1> <div class="container w-full mx-auto text-lg px-4 max-w-xl space-y-2"> - <form on:submit|preventDefault={submit} class="space-y-2"> + <form onsubmit={preventDefault(submit)} class="space-y-2"> <textarea use:focus name="text" @@ -41,7 +45,7 @@ class="w-full p-4 border rounded-xl h-48 text-xl" bind:value={text} autocapitalize="none" - /> +></textarea> <button bind:this={el} type="submit" diff --git a/src/routes/(app)/account/pass/+page.svelte b/src/routes/(app)/account/pass/+page.svelte index 5becf337..62ef9b8e 100644 --- a/src/routes/(app)/account/pass/+page.svelte +++ b/src/routes/(app)/account/pass/+page.svelte @@ -1,4 +1,6 @@ <script lang="ts"> + import { preventDefault } from 'svelte/legacy'; + import { tick, onMount } from "svelte"; import { t } from "$lib/translations"; import { mnemonic } from "$lib/store"; @@ -15,12 +17,12 @@ import { goto } from "$app/navigation"; import { HDKey } from "@scure/bip32"; - export let data; + let { data } = $props(); let { user } = data; - let submitting; + let submitting = $state(); - let confirm, password, revealPassword, revealConfirm; + let confirm = $state(), password = $state(), revealPassword = $state(), revealConfirm = $state(); let type = "bitcoin"; let name = $t("accounts.savings"); @@ -70,7 +72,7 @@ </div> <form - on:submit|preventDefault={submit} + onsubmit={preventDefault(submit)} class="container w-full mx-auto text-lg px-4 max-w-xl space-y-5" > <p class="text-secondary mb-1"> @@ -100,7 +102,7 @@ <button tabindex="-1" type="button" - on:click={() => (revealPassword = !revealPassword)} + onclick={() => (revealPassword = !revealPassword)} class="absolute right-5 -translate-y-1/2 top-1/2" > <Icon icon={revealPassword ? "eye" : "eye-off"} /> @@ -129,7 +131,7 @@ <button type="button" tabindex="-1" - on:click={() => (revealConfirm = !revealConfirm)} + onclick={() => (revealConfirm = !revealConfirm)} class="absolute right-5 -translate-y-1/2 top-1/2" > <Icon icon={revealConfirm ? "eye" : "eye-off"} /> diff --git a/src/routes/(app)/account/savings/+page.svelte b/src/routes/(app)/account/savings/+page.svelte index 2461bd20..d0474636 100644 --- a/src/routes/(app)/account/savings/+page.svelte +++ b/src/routes/(app)/account/savings/+page.svelte @@ -13,7 +13,7 @@ <a href="/account/seed" class="block"> <div class="card card-side shadow shadow-base-400 p-8 hover:bg-base-200"> <figure class="w-20"> - <iconify-icon icon="ph:file-plus-bold" width="64" /> + <iconify-icon icon="ph:file-plus-bold" width="64"></iconify-icon> </figure> <div> <div class="text-xl">{$t("accounts.create")}</div> @@ -24,7 +24,7 @@ <a href="/account/import" class="block"> <div class="card card-side shadow p-8 hover:bg-base-200"> <figure class="w-20"> - <iconify-icon icon="ph:folder-open-bold" width="64" /> + <iconify-icon icon="ph:folder-open-bold" width="64"></iconify-icon> </figure> <div> <div class="text-xl">{$t("accounts.import")}</div> diff --git a/src/routes/(app)/account/seed/+page.svelte b/src/routes/(app)/account/seed/+page.svelte index 5d828369..b3e7d57c 100644 --- a/src/routes/(app)/account/seed/+page.svelte +++ b/src/routes/(app)/account/seed/+page.svelte @@ -9,7 +9,7 @@ import { generateMnemonic } from "@scure/bip39"; import { wordlist } from "@scure/bip39/wordlists/english"; - export let data; + let { data } = $props(); let { user } = data; onMount(async () => { @@ -36,7 +36,7 @@ <button type="button" class="flex gap-2 text-center break-all rounded-2xl hover:opacity-80 py-3 px-4 w-full mx-auto justify-center border whitespace-nowrap mb-2" - on:click={generate} + onclick={generate} > <Icon icon="random" style="w-8 my-auto" /> <div class="my-auto">{$t("accounts.regenerate")}</div> @@ -45,7 +45,7 @@ <button type="button" class="flex gap-2 text-center break-all rounded-2xl hover:opacity-80 py-3 px-4 w-full mx-auto justify-center border whitespace-nowrap mb-2" - on:click={() => copy($mnemonic)} + onclick={() => copy($mnemonic)} > <Icon icon="copy" style="w-8 my-auto" /> <div class="my-auto"> diff --git a/src/routes/(app)/admin/+layout.svelte b/src/routes/(app)/admin/+layout.svelte index 54905ab0..39cfe5ed 100644 --- a/src/routes/(app)/admin/+layout.svelte +++ b/src/routes/(app)/admin/+layout.svelte @@ -1,10 +1,10 @@ <script> import LandingHeader from "$comp/LandingHeader.svelte"; - export let data; + let { data, children } = $props(); let { user } = data; </script> <LandingHeader {user} /> <main class="container px-10 md:px-40 mx-auto min-h-[600px] pb-20"> - <slot /> + {@render children?.()} </main> diff --git a/src/routes/(app)/admin/+page.svelte b/src/routes/(app)/admin/+page.svelte index 214bf5b3..ccaa8794 100644 --- a/src/routes/(app)/admin/+page.svelte +++ b/src/routes/(app)/admin/+page.svelte @@ -1,9 +1,9 @@ <script> import { post } from "$lib/utils"; - export let data; + let { data } = $props(); let reset = (username) => post(`/reset`, { password }); let { users } = data; - let password; + let password = $state(); </script> {#each users as { balance, username, expected }} @@ -15,7 +15,7 @@ <div> <button class="text-sm md:text-lg rounded-full border py-2 px-4 hover:opacity-80 min-w-[72px] bg-black text-white" - on:click={() => reset(username)}>Reset</button + onclick={() => reset(username)}>Reset</button > </div> </div> diff --git a/src/routes/(app)/ecash/[id]/[...version]/+layout.svelte b/src/routes/(app)/ecash/[id]/[...version]/+layout.svelte index f9c80329..d0d06046 100644 --- a/src/routes/(app)/ecash/[id]/[...version]/+layout.svelte +++ b/src/routes/(app)/ecash/[id]/[...version]/+layout.svelte @@ -3,7 +3,7 @@ import { t } from "$lib/translations"; import Icon from "$comp/Icon.svelte"; - export let data; + let { data, children } = $props(); let { id, rates, user, token, total, spent, external, mint } = data; let currency = user?.currency || "USD"; @@ -11,8 +11,8 @@ let amount = total - spent; - $: amountFiat = parseFloat(((amount * rate) / sats).toFixed(2)); - $: spentFiat = parseFloat(((spent * rate) / sats).toFixed(2)); + let amountFiat = $derived(parseFloat(((amount * rate) / sats).toFixed(2))); + let spentFiat = $derived(parseFloat(((spent * rate) / sats).toFixed(2))); </script> <div class="container px-4 max-w-lg mx-auto space-y-5 mt-20"> @@ -52,5 +52,5 @@ </div> {/if} - <slot /> + {@render children?.()} </div> diff --git a/src/routes/(app)/ecash/[id]/[...version]/+page.svelte b/src/routes/(app)/ecash/[id]/[...version]/+page.svelte index b350b124..47126c78 100644 --- a/src/routes/(app)/ecash/[id]/[...version]/+page.svelte +++ b/src/routes/(app)/ecash/[id]/[...version]/+page.svelte @@ -4,11 +4,10 @@ import { t } from "$lib/translations"; import { page } from "$app/stores"; - export let data; - export let form; + let { data, form } = $props(); let link = $page.url.href; - let { id, total, version, token, external, spent } = data; + let { id, total, version, token, external, spent } = $state(data); </script> {#if form?.error} @@ -20,8 +19,8 @@ {/if} <div class="flex flex-wrap gap-2 text-xl"> - <button type="button" class="btn" on:click={() => copy(link)}> - <iconify-icon icon="ph:link-bold" width="32" /> + <button type="button" class="btn" onclick={() => copy(link)}> + <iconify-icon icon="ph:link-bold" width="32"></iconify-icon> <div class="my-auto">{$t("payments.shareLink")}</div> </button> @@ -33,7 +32,7 @@ icon="ph:hand-coins-bold" width="32" flip="horizontal" - /> +></iconify-icon> <div class="my-auto">{$t("payments.swap")}</div> </button> </a> @@ -45,7 +44,7 @@ icon="ph:hand-coins-bold" width="32" flip="horizontal" - /> +></iconify-icon> <div class="my-auto">{$t("payments.redeem")}</div> </button> </form> @@ -54,7 +53,7 @@ <button class="btn break-all !h-auto py-5 font-normal leading-normal" - on:click={() => copy(token)} + onclick={() => copy(token)} > {token} </button> @@ -62,14 +61,14 @@ {#if version === 4} <a data-sveltekit-reload href={`/ecash/${id}/3`} class="contents"> <button type="button" class="btn"> - <iconify-icon icon="ph:gear-bold" width="32" /> + <iconify-icon icon="ph:gear-bold" width="32"></iconify-icon> <div class="my-auto">{$t("payments.legacyVersion")}</div> </button> </a> {:else} <a data-sveltekit-reload href={`/ecash/${id}`} class="contents"> <button type="button" class="btn"> - <iconify-icon icon="ph:gear-bold" width="32" /> + <iconify-icon icon="ph:gear-bold" width="32"></iconify-icon> <div class="my-auto">{$t("payments.newVersion")}</div> </button> </a> diff --git a/src/routes/(app)/ecash/[id]/[...version]/swap/+page.svelte b/src/routes/(app)/ecash/[id]/[...version]/swap/+page.svelte index ee22cea2..c434c9b4 100644 --- a/src/routes/(app)/ecash/[id]/[...version]/swap/+page.svelte +++ b/src/routes/(app)/ecash/[id]/[...version]/swap/+page.svelte @@ -1,5 +1,5 @@ <script> - export let data; + let { data } = $props(); </script> <div class="text-center"> diff --git a/src/routes/(app)/forgot/+page.svelte b/src/routes/(app)/forgot/+page.svelte index 378262cc..eb981734 100644 --- a/src/routes/(app)/forgot/+page.svelte +++ b/src/routes/(app)/forgot/+page.svelte @@ -6,8 +6,8 @@ import Spinner from "$comp/Spinner.svelte"; import { fly } from "svelte/transition"; - export let form; - let email; + let { form } = $props(); + let email = $state(); let loading; </script> diff --git a/src/routes/(app)/fund/[id]/+page.svelte b/src/routes/(app)/fund/[id]/+page.svelte index b81e2917..0931075a 100644 --- a/src/routes/(app)/fund/[id]/+page.svelte +++ b/src/routes/(app)/fund/[id]/+page.svelte @@ -9,7 +9,7 @@ import { types, copy, f, s, sat, sats } from "$lib/utils"; import { loginRedirect } from "$lib/store"; - export let data; + let { data } = $props(); let { amount, src, payments, rates, user } = data; let { id } = $page.params; @@ -19,10 +19,10 @@ let currency = user ? user.currency : "CAD"; let rate = rates[currency]; - $: amountFiat = parseFloat(((amount * rate) / sats).toFixed(2)); + let amountFiat = $derived(parseFloat(((amount * rate) / sats).toFixed(2))); $loginRedirect = $page.url.pathname; - let show; + let show = $state(); let toggle = () => (show = !show); </script> @@ -83,14 +83,14 @@ <div class="flex gap-2" data-sveltekit-prefetch="off"> <button class="rounded-full border py-3 px-2 font-bold hover:opacity-80 flex gap-1 w-full justify-center" - on:click={toggle} + onclick={toggle} > <Icon icon="qr" style="invert" /> {show ? $t("payments.hide") : $t("payments.show")} QR </button> <button class="rounded-full border py-3 px-2 font-bold hover:opacity-80 flex gap-1 w-full justify-center" - on:click={() => copy($page.url.host + $page.url.pathname)} + onclick={() => copy($page.url.host + $page.url.pathname)} > <Icon icon="copy" style="w-6" /> {$t("payments.copyLink")} diff --git a/src/routes/(app)/fund/[id]/sweep/+page.svelte b/src/routes/(app)/fund/[id]/sweep/+page.svelte index 927c59d3..a34a8610 100644 --- a/src/routes/(app)/fund/[id]/sweep/+page.svelte +++ b/src/routes/(app)/fund/[id]/sweep/+page.svelte @@ -4,11 +4,11 @@ import Icon from "$comp/Icon.svelte"; import { t } from "$lib/translations"; - export let data; + let { data } = $props(); let { amount, id, user, rates } = data; let { currency } = user; - $: rate = rates[currency]; + let rate = $derived(rates[currency]); </script> <div class="container px-4 max-w-xl mx-auto mt-10 space-y-5 text-center"> @@ -33,7 +33,7 @@ </div> <a href={`/payments`}> - <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50" /> + <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50"></div> </a> <div class="flex justify-center"> diff --git a/src/routes/(app)/fund/[id]/withdraw/+page.svelte b/src/routes/(app)/fund/[id]/withdraw/+page.svelte index 0ad3c2cf..89654d23 100644 --- a/src/routes/(app)/fund/[id]/withdraw/+page.svelte +++ b/src/routes/(app)/fund/[id]/withdraw/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { t } from "$lib/translations"; import { enhance } from "$app/forms"; import Icon from "$comp/Icon.svelte"; @@ -8,25 +10,29 @@ import { back } from "$lib/utils"; import { pin } from "$lib/store"; - export let data; - export let form; + let { data, form } = $props(); let { rates } = data; - let { amount, id } = $page.params; - let { currency } = data.user; - let loading; + let { amount, id } = $state($page.params); + let { currency } = $state(data.user); + let loading = $state(); let submit = () => (loading = true); - $: update(form); let update = () => { if (form?.message.includes("pin")) $pin = undefined; loading = false; }; - $: rate = rates[currency]; + run(() => { + update(form); + }); + let rate; + run(() => { + rate = rates[currency]; + }); </script> -<button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" on:click={back}> +<button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" onclick={back}> <Icon icon="arrow-left" style="w-10" /> </button> @@ -39,7 +45,7 @@ <div class="container px-4 mt-20 max-w-xl mx-auto"> <Numpad bind:amount bind:currency bind:rate /> - <form method="POST" use:enhance on:submit={submit}> + <form method="POST" use:enhance onsubmit={submit}> <input name="id" value={id} type="hidden" /> <input name="amount" value={amount} type="hidden" /> <input name="pin" value={$pin} type="hidden" /> diff --git a/src/routes/(app)/generate/+page.svelte b/src/routes/(app)/generate/+page.svelte index 49d75dc6..72ca2485 100644 --- a/src/routes/(app)/generate/+page.svelte +++ b/src/routes/(app)/generate/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { fail, post, wait } from "$lib/utils"; import { onMount } from "svelte"; import { goto, invalidate } from "$app/navigation"; @@ -8,10 +10,10 @@ import { generate } from "$lib/nostr"; import { browser } from "$app/environment"; - export let data; - let { user } = data; + let { data } = $props(); + let { user } = $state(data); - let loaded; + let loaded = $state(); let gen = async () => { if (!browser) return; @@ -43,7 +45,9 @@ onMount(() => browser && setTimeout(() => (loaded = true) && gen(), 50)); - $: $pin?.length === 6 && gen(user); + run(() => { + $pin?.length === 6 && gen(user); + }); </script> {#if loaded && user?.haspin && $pin?.length !== 6} diff --git a/src/routes/(app)/invoice/[id]/[email protected] b/src/routes/(app)/invoice/[id]/[email protected] index 62c05db1..05fd603f 100644 --- a/src/routes/(app)/invoice/[id]/[email protected] +++ b/src/routes/(app)/invoice/[id]/[email protected] @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { SvelteToast } from "@zerodevx/svelte-toast"; import { onDestroy, onMount } from "svelte"; import { close, connect, send } from "$lib/socket"; @@ -22,16 +24,14 @@ import { t, locale, loading } from "$lib/translations"; import { goto, onNavigate } from "$app/navigation"; - export let data; + let { data, children } = $props(); - let { generate, rate, user, subject, token, rates, theme } = data; + let { generate, rate, user, subject, token, rates, theme } = $state(data); - $: update(data); let update = (data) => { ({ rate, user, subject, token, rates, theme } = data); }; - $: theme = $themeStore; $themeStore = theme; onMount(async () => { @@ -58,7 +58,6 @@ } }); - $: browser && connect(token); let lost, checkTimer, @@ -84,6 +83,15 @@ clearTimeout(expireTimer); } }); + run(() => { + update(data); + }); + run(() => { + theme = $themeStore; + }); + run(() => { + browser && connect(token); + }); </script> {#if browser && user && $passwordPrompt} @@ -110,7 +118,7 @@ <main class="min-h-dvh" data-theme={theme}> <AppHeader {user} {subject} /> {#if !$loading} - <slot /> + {@render children?.()} {/if} </main> diff --git a/src/routes/(app)/invoice/[id]/+page.svelte b/src/routes/(app)/invoice/[id]/+page.svelte index ae208779..fef43e4d 100644 --- a/src/routes/(app)/invoice/[id]/+page.svelte +++ b/src/routes/(app)/invoice/[id]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from "svelte/legacy"; + import { enhance } from "$app/forms"; import { send } from "$lib/socket"; import { btc, post, copy, f, get, types, sat, s, sats } from "$lib/utils"; @@ -13,7 +15,7 @@ import { t } from "$lib/translations"; import { goto, invalidate } from "$app/navigation"; - export let data; + let { data } = $props(); let showOptions; @@ -24,8 +26,7 @@ let readingerror = (e) => console.log("nfc error", e); - $: refresh(data); - let { invoice, id, subject, user, src } = data; + let { invoice, id, subject, user, src } = $state(data); let { aid, amount, @@ -35,9 +36,9 @@ text, tip, user: { username, currency }, - } = invoice; + } = $state(invoice); - let qr; + let qr = $state(); let tipPercent = 0; let refresh = async (data) => { @@ -64,9 +65,6 @@ tipPercent = (tip / amount) * 100; }; - $: amountFiat = parseFloat(((amount * rate) / sats).toFixed(2)); - $: tipAmount = ((tip * rate) / sats).toFixed(2); - let subbed = {}; onMount(async () => { @@ -81,11 +79,6 @@ } }); - $: link = [types.bitcoin, types.liquid].includes(type) - ? text - : `lightning:${text}`; - $: txt = [types.bitcoin, types.liquid].includes(type) ? hash : text; - let setType = async (type) => { invoice.type = type; ({ id } = await post(`/invoice`, { @@ -96,7 +89,7 @@ goto(`./${id}?options=true`, { invalidateAll: true, noScroll: true }); }; - let setAmount = async () => { + let setAmount = $state(async () => { if (typeof $amountPrompt === "undefined") $amountPrompt = true; settingAmount = false; amount = newAmount; @@ -112,39 +105,57 @@ else url += "?options=true"; goto(url, { invalidateAll: true, noScroll: true }); - }; + }); - let newAmount; - let settingAmount; - let toggleAmount = () => (settingAmount = !settingAmount); - let fiat; - let submit; + let newAmount = $state(); + let settingAmount = $state(); + let toggleAmount = $state(() => (settingAmount = !settingAmount)); + let fiat = $state(true); + let submit = $state(); + run(() => { + refresh(data); + }); + let amountFiat; + run(() => { + amountFiat = parseFloat(((amount * rate) / sats).toFixed(2)); + }); + let tipAmount = $derived(((tip * rate) / sats).toFixed(2)); + let link; + run(() => { + link = [types.bitcoin, types.liquid].includes(type) + ? text + : `lightning:${text}`; + }); + let txt; + run(() => { + txt = [types.bitcoin, types.liquid].includes(type) ? hash : text; + }); </script> <div class="invoice container mx-auto max-w-xl px-4 space-y-2"> <InvoiceData - bind:src - bind:link - bind:qr - bind:txt - bind:invoice - bind:amount - bind:amountFiat - bind:currency - bind:tip - bind:rate - bind:showQr={$showQr} + {src} + {link} + {qr} + {txt} + {invoice} + {amount} + {amountFiat} + {currency} + {tip} + {rate} + showQr={$showQr} /> <InvoiceActions - bind:toggleAmount - bind:user - bind:invoice + {toggleAmount} + {user} + {invoice} {copy} - bind:link - bind:type + {link} + {type} {types} - bind:txt + {txt} t={$t} bind:showQr={$showQr} /> @@ -153,14 +164,14 @@ </div> <SetAmount - bind:currency - bind:rate - bind:fiat - bind:submit - bind:settingAmount - bind:setAmount bind:newAmount - bind:toggleAmount + bind:fiat + {currency} + {rate} + {submit} + {settingAmount} + {setAmount} + {toggleAmount} amountPrompt={$amountPrompt} t={$t} /> diff --git a/src/routes/(app)/invoice/[id]/memo/+page.svelte b/src/routes/(app)/invoice/[id]/memo/+page.svelte index 4d23ff19..02f4a5d9 100644 --- a/src/routes/(app)/invoice/[id]/memo/+page.svelte +++ b/src/routes/(app)/invoice/[id]/memo/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { onMount } from "svelte"; import { browser } from "$app/environment"; import { invoice as inv, request } from "$lib/store"; @@ -17,11 +19,10 @@ import { enhance } from "$app/forms"; let submitting; - let submit; + let submit = $state(); - export let data; - $: refresh(data); - let { invoice, id, user, rates } = data; + let { data } = $props(); + let { invoice, id, user, rates } = $state(data); let { amount, hash, @@ -34,7 +35,7 @@ text, tip, user: { username, currency }, - } = invoice; + } = $state(invoice); invoice.memo = user?.username; @@ -55,6 +56,9 @@ user: { username }, } = invoice); }; + run(() => { + refresh(data); + }); </script> <form diff --git a/src/routes/(app)/invoice/[id]/paid/+page.svelte b/src/routes/(app)/invoice/[id]/paid/+page.svelte index b3b6e71a..1bbba082 100644 --- a/src/routes/(app)/invoice/[id]/paid/+page.svelte +++ b/src/routes/(app)/invoice/[id]/paid/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { scale } from "svelte/transition"; import Icon from "$comp/Icon.svelte"; import { toast } from "@zerodevx/svelte-toast"; @@ -6,15 +8,17 @@ import { t } from "$lib/translations"; import { fiat, f, s, sat, sats } from "$lib/utils"; - export let data; - let amount, currency, rate, received, pending, tip, user, id; - $: update(data); + let { data } = $props(); + let amount, currency = $state(), rate = $state(), received = $state(), pending = $state(), tip = $state(), user = $state(), id; let update = (data) => { ({ amount, currency, rate, received, pending, tip, user, id } = data.invoice); }; toast.pop(0); + run(() => { + update(data); + }); </script> <div class="container px-4 text-center mx-auto"> @@ -77,7 +81,7 @@ </div> <a href={`/${user.username}`}> - <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50" /> + <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50"></div> </a> <div class="flex justify-center"> diff --git a/src/routes/(app)/invoice/[id]/tip/+page.svelte b/src/routes/(app)/invoice/[id]/tip/+page.svelte index ff3da46e..53f0eb4b 100644 --- a/src/routes/(app)/invoice/[id]/tip/+page.svelte +++ b/src/routes/(app)/invoice/[id]/tip/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { onMount } from "svelte"; import { browser } from "$app/environment"; import { invoice as inv, request } from "$lib/store"; @@ -11,10 +13,10 @@ import { tick } from "svelte"; const tipAmounts = ["No", "10%", "15%", "20%"]; - let showCustomAmount; + let showCustomAmount = $state(); - let customInput; - let customTipAmount; + let customInput = $state(); + let customTipAmount = $state(); let apply = async () => { if (customTipAmount > 0) { @@ -40,7 +42,7 @@ tipPercent = e.target.value; }; - let submitting; + let submitting = $state(); const handleTipButtonClick = async (amount) => { submitting = true; if (amount === "No") { @@ -53,11 +55,10 @@ submit.click(); }; - let submit; + let submit = $state(); - export let data; - $: refresh(data); - let { invoice, id, user, rates } = data; + let { data } = $props(); + let { invoice, id, user, rates } = $state(data); let { aid, amount, @@ -70,10 +71,10 @@ text, tip, user: { username, currency }, - } = invoice; + } = $state(invoice); let qr; - let tipPercent = 0; + let tipPercent = $state(0); let fullscreen; @@ -97,18 +98,27 @@ tipPercent = (tip / amount) * 100; }; - $: currency = user?.currency || invoice.currency; - $: rate = invoice.rate * (rates[currency] / rates[invoice.currency]); - $: tip = Math.round((amount / 100) * tipPercent); - $: amountFiat = parseFloat(((amount * rate) / sats).toFixed(2)); - $: tipAmount = ((tip * rate) / sats).toFixed(2); - $: invoiceAmountFiatFormatted = f(amountFiat, currency); onMount(() => ($request = undefined)); + run(() => { + refresh(data); + }); + run(() => { + currency = user?.currency || invoice.currency; + }); + run(() => { + rate = invoice.rate * (rates[currency] / rates[invoice.currency]); + }); + run(() => { + tip = Math.round((amount / 100) * tipPercent); + }); + let amountFiat = $derived(parseFloat(((amount * rate) / sats).toFixed(2))); + let tipAmount = $derived(((tip * rate) / sats).toFixed(2)); + let invoiceAmountFiatFormatted = $derived(f(amountFiat, currency)); </script> <div class="container px-4 max-w-lg text-center mx-auto"> @@ -154,10 +164,10 @@ <div class="space-y-2"> {#if tip} - <button type="button" class="btn" on:click={() => submit.click()} + <button type="button" class="btn" onclick={() => submit.click()} >Next</button > - <button type="button" class="btn" on:click={() => (tipPercent = 0)} + <button type="button" class="btn" onclick={() => (tipPercent = 0)} >Reset</button > {:else} @@ -168,14 +178,14 @@ type="button" class="btn" class:active={active(amount, tipPercent)} - on:click={() => handleTipButtonClick(amount)}>{amount}</button + onclick={() => handleTipButtonClick(amount)}>{amount}</button > {:else} <button type="button" class="btn" class:active={active(amount, tipPercent)} - on:click={() => handleTipButtonClick(amount)}>{amount}</button + onclick={() => handleTipButtonClick(amount)}>{amount}</button > {/if} {/each} @@ -186,21 +196,21 @@ <button type="button" class="btn" - on:click={() => (showCustomAmount = true)}>Custom</button + onclick={() => (showCustomAmount = true)}>Custom</button > </div> {/if} - <button type="submit" bind:this={submit} /> + <button type="submit" bind:this={submit}></button> </form> {#if showCustomAmount} - <form on:submit|preventDefault={apply} class="space-y-2"> + <form onsubmit={preventDefault(apply)} class="space-y-2"> <input bind:this={customInput} type="number" step="0.01" - on:input={(e) => handleCustomTipAmount(e)} + oninput={(e) => handleCustomTipAmount(e)} placeholder={$t("payments.amount")} use:focus /> diff --git a/src/routes/(app)/items/[id]/+page.svelte b/src/routes/(app)/items/[id]/+page.svelte index 65720350..9629f311 100644 --- a/src/routes/(app)/items/[id]/+page.svelte +++ b/src/routes/(app)/items/[id]/+page.svelte @@ -1,12 +1,15 @@ <script> + import { run } from 'svelte/legacy'; + import { t } from "$lib/translations"; import ItemForm from "$comp/ItemForm.svelte"; import { fail } from "$lib/utils"; - export let data; - export let form; + let { data, form } = $props(); - $: form?.message && fail(form.message); + run(() => { + form?.message && fail(form.message); + }); let { item, user } = data; </script> diff --git a/src/routes/(app)/items/create/+page.svelte b/src/routes/(app)/items/create/+page.svelte index b82889c9..b756e73e 100644 --- a/src/routes/(app)/items/create/+page.svelte +++ b/src/routes/(app)/items/create/+page.svelte @@ -1,12 +1,15 @@ <script> + import { run } from 'svelte/legacy'; + import { t } from "$lib/translations"; import ItemForm from "$comp/ItemForm.svelte"; import { fail } from "$lib/utils"; - export let data; - export let form; + let { data, form } = $props(); - $: form?.message && fail(form.message); + run(() => { + form?.message && fail(form.message); + }); let { user } = data; let item = {}; </script> diff --git a/src/routes/(app)/ln/[lnurl]/+page.svelte b/src/routes/(app)/ln/[lnurl]/+page.svelte index 236a2a25..386df9d2 100644 --- a/src/routes/(app)/ln/[lnurl]/+page.svelte +++ b/src/routes/(app)/ln/[lnurl]/+page.svelte @@ -1,7 +1,7 @@ <script> import Lnurlp from "$comp/Lnurlp.svelte"; import Lnurlw from "$comp/Lnurlw.svelte"; - export let data; + let { data } = $props(); let { tag } = data; </script> diff --git a/src/routes/(app)/ln/withdrawal/sent/+page.svelte b/src/routes/(app)/ln/withdrawal/sent/+page.svelte index 143a92f4..e06e3c2c 100644 --- a/src/routes/(app)/ln/withdrawal/sent/+page.svelte +++ b/src/routes/(app)/ln/withdrawal/sent/+page.svelte @@ -4,7 +4,7 @@ import { toast } from "@zerodevx/svelte-toast"; import { t } from "$lib/translations"; - export let data; + let { data } = $props(); let { user } = data; toast.pop(0); </script> @@ -20,7 +20,7 @@ </div> <a href={`/payments`}> - <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50" /> + <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50"></div> </a> <div class="flex justify-center"> diff --git a/src/routes/(app)/messages/+page.svelte b/src/routes/(app)/messages/+page.svelte index 61464770..269a5de3 100644 --- a/src/routes/(app)/messages/+page.svelte +++ b/src/routes/(app)/messages/+page.svelte @@ -1,20 +1,21 @@ <script> + import { run } from 'svelte/legacy'; + import { t } from "$lib/translations"; import Avatar from "$comp/Avatar.svelte"; import { event as e, password } from "$lib/store"; import { browser } from "$app/environment"; import { decrypt } from "$lib/nostr"; - export let data; + let { data } = $props(); let { messages, notes, invoices, sent, received, subject, user, rates } = - data; - $: refresh(data); + $state(data); let refresh = (d) => ({ messages, notes, invoices, sent, received, subject, user, rates } = d); let keys = new Set(); - let latest = []; + let latest = $state([]); let ready; e.subscribe(async (event) => { @@ -35,7 +36,6 @@ } }); - $: initialize($password); let initialize = async (p) => { let i = 0; ready = false; @@ -61,6 +61,12 @@ latest = latest; ready = true; }; + run(() => { + refresh(data); + }); + run(() => { + initialize($password); + }); </script> <div class="container w-full mx-auto text-lg px-4 max-w-xl space-y-5"> diff --git a/src/routes/(app)/messages/[recipient]/+page.svelte b/src/routes/(app)/messages/[recipient]/+page.svelte index 9b9f6f47..bc1a6383 100644 --- a/src/routes/(app)/messages/[recipient]/+page.svelte +++ b/src/routes/(app)/messages/[recipient]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { cubicInOut } from "svelte/easing"; import { browser } from "$app/environment"; import { t } from "$lib/translations"; @@ -13,7 +15,7 @@ import { tick, onMount } from "svelte"; import { getEventHash } from "nostr-tools"; - export let data; + let { data } = $props(); function fadeScale( node, @@ -36,10 +38,9 @@ }; } - let { messages, recipient, user } = data; - let input, pane; + let { messages, recipient, user } = $state(data); + let input, pane = $state(); - $: initialize($password); let initialize = async (p) => { await Promise.all( messages.map( @@ -61,7 +62,7 @@ } }); - let sent, submitting, message; + let sent, submitting, message = $state(); let submit = async () => { submitting = true; @@ -109,6 +110,9 @@ submit(); } }; + run(() => { + initialize($password); + }); </script> <div class="container max-w-xl mx-auto px-4 space-y-5"> @@ -116,7 +120,7 @@ type="button" class="hover:opacity-80" data-sveltekit-preload-data="false" - on:click={back} + onclick={back} > <Icon icon="arrow-left" style="w-10" /> </button> @@ -162,7 +166,7 @@ <form method="POST" class="w-full border rounded-xl outline-none gap-4 flex p-0 pr-2" - on:submit|preventDefault={submit} + onsubmit={preventDefault(submit)} > <input type="hidden" name="requester_id" value={user.id} /> <input type="hidden" name="recipient" value={recipient.username} /> @@ -172,8 +176,8 @@ contenteditable class="grow break-all py-4 outline-none mt-0 pl-4" bind:innerHTML={message} - on:keydown={keydown} - /> + onkeydown={keydown} +></div> <button type="submit" class="my-auto shrink-0"> <Icon icon="send" style="w-8" /> </button> diff --git a/src/routes/(app)/pay/[username]/[...amount]/+page.svelte b/src/routes/(app)/pay/[username]/[...amount]/+page.svelte index bf2e877e..4fbd0b64 100644 --- a/src/routes/(app)/pay/[username]/[...amount]/+page.svelte +++ b/src/routes/(app)/pay/[username]/[...amount]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from "svelte/legacy"; + import { t } from "$lib/translations"; import { goto } from "$app/navigation"; import { pin } from "$lib/store"; @@ -10,22 +12,19 @@ import { page } from "$app/stores"; import { f, fail, post, s, sat, sats } from "$lib/utils"; - export let data; - export let form; + let { data, form } = $props(); - let { subject, rate, rates, user } = data; + let { subject, rate, rates, user } = $state(data); let currency = subject?.currency || "USD"; - let next; + let next = $state(); - let amount = form?.amount || data.amount; - let a, - af, - fiat = !amount, - hash, + let amount = $state(form?.amount || data.amount); + let a = $state(), + af = $state(0), + fiat = $state(!amount), + hash = $state(), amountFiat = 0; - $: r = rate || rates[subject?.currency]; - let setAmount = async () => { amount = a; amountFiat = parseFloat(af).toFixed(2); @@ -49,14 +48,20 @@ goto(`/send/invoice/${id}`); }; - let loading; + let loading = $state(); let submit = () => (loading = true); - $: update(form); let update = () => { if (form?.message?.includes("pin")) $pin = undefined; loading = false; }; + let r; + run(() => { + r = rate || rates[subject?.currency]; + }); + run(() => { + update(form); + }); </script> {#if form?.message} @@ -72,10 +77,10 @@ {currency} bind:fiat bind:rate={r} - bind:submit={next} + submit={next} /> - <form method="POST" use:enhance on:submit={submit}> + <form method="POST" use:enhance onsubmit={submit}> <input name="amount" value={amount} type="hidden" /> <input name="username" value={subject.username} type="hidden" /> <input name="pin" value={$pin} type="hidden" /> @@ -98,8 +103,8 @@ type="button" bind:this={next} class="btn btn-accent" - on:click={setAmount} - on:keydown={setAmount} + onclick={setAmount} + onkeydown={setAmount} > {$t("payments.next")}</button > diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte index 150c2bc4..fd5ea95f 100644 --- a/src/routes/(app)/payment/[id]/+page.svelte +++ b/src/routes/(app)/payment/[id]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { browser } from "$app/environment"; import { onMount, tick } from "svelte"; import { t, loading } from "$lib/translations"; @@ -19,11 +21,10 @@ import { PUBLIC_EXPLORER, PUBLIC_LIQUID_EXPLORER } from "$env/static/public"; import locales from "$lib/locales"; - export let data; - let { user, payment: p } = data; + let { data } = $props(); + let { user, payment: p } = $state(data); let locale = locales[user.language]; - $: refresh(data); let refresh = (d) => { ({ user, payment: p } = d); ({ @@ -65,7 +66,7 @@ ourfee, fee, currency, - } = p; + } = $state(p); let a = Math.abs(amount); let expl = { @@ -86,11 +87,11 @@ } }; - let txid, vout; + let txid = $state(), vout = $state(); if (amount > 0) [txid, vout] = ref.split(":"); else txid = hash; - let direction = ""; + let direction = $state(""); onMount(() => { direction = amount > 0 ? $t("payments.from") : $t("payments.to"); @@ -98,6 +99,9 @@ direction = direction[0].toUpperCase() + direction.substr(1, direction.length); }); + run(() => { + refresh(data); + }); </script> <div class="container mx-auto max-w-lg px-4 space-y-8 break-all text-2xl"> @@ -222,7 +226,7 @@ </div> <button class="flex font-bold hover:opacity-80 mb-auto my-auto" - on:click={() => copy(txid)} + onclick={() => copy(txid)} > <Icon icon="copy" style="ml-2 w-12 my-auto" /> </button> @@ -237,7 +241,7 @@ <div>{path}</div> <button class="flex font-bold hover:opacity-80 mb-auto my-auto" - on:click={() => copy(path)} + onclick={() => copy(path)} > <Icon icon="copy" style="ml-2 w-12 my-auto" /> </button> diff --git a/src/routes/(app)/payment/[id]/plain/+page.svelte b/src/routes/(app)/payment/[id]/plain/+page.svelte index c63a9d7f..7d5c09aa 100644 --- a/src/routes/(app)/payment/[id]/plain/+page.svelte +++ b/src/routes/(app)/payment/[id]/plain/+page.svelte @@ -19,7 +19,7 @@ import { format } from "date-fns"; import { PUBLIC_EXPLORER as expl } from "$env/static/public"; - export let data; + let { data } = $props(); let { user, payment: p } = data; let { username } = user; @@ -84,5 +84,5 @@ </div> <a href={`/payment/${id}`}> - <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50" /> + <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50"></div> </a> diff --git a/src/routes/(app)/payments/[...page]/+page.svelte b/src/routes/(app)/payments/[...page]/+page.svelte index ba2e4992..2735491c 100644 --- a/src/routes/(app)/payments/[...page]/+page.svelte +++ b/src/routes/(app)/payments/[...page]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import Avatar from "$comp/Avatar.svelte"; import { onMount } from "svelte"; import { format } from "date-fns"; @@ -9,9 +11,9 @@ import { differenceInDays, getUnixTime, sub } from "date-fns"; import { goto, invalidate } from "$app/navigation"; import locales from "$lib/locales"; - export let data; + let { data } = $props(); - let { start, end, user, rates, payments } = data; + let { start, end, user, rates, payments } = $state(data); let locale = locales[user.language]; let change = ({ target: { value } }) => goto(value); @@ -21,7 +23,7 @@ return `/p/${p.id}`; }; - $: presets = [ + let presets = $derived([ { title: $t("payments.day"), start: sub(new Date(), { days: 1 }), @@ -42,27 +44,33 @@ start: sub(new Date(), { years: 5 }), end: null, }, - ]; + ]); - $: selection = start + let selection = $derived(start ? presets.findIndex( (p) => Math.abs(differenceInDays(new Date(start * 1000), p.start)) < 1, ) - : 0; + : 0); - let p, - incoming, - outgoing, - pages = []; - $: data && - ({ page: p, pages, start, end, incoming, outgoing, payments } = data); + let p = $state(), + incoming = $state(), + outgoing = $state(), + pages = $state([]); + run(() => { + data && + ({ page: p, pages, start, end, incoming, outgoing, payments } = data); + }); - $: $page && ($newPayment = false); - $: $newPayment && invalidate(`/users/${user.username}`); + run(() => { + $page && ($newPayment = false); + }); + run(() => { + $newPayment && invalidate(`/users/${user.username}`); + }); - $: path = $page.params.page + let path = $derived($page.params.page ? $page.url.pathname.substring(0, $page.url.pathname.lastIndexOf("/")) - : $page.url.pathname; + : $page.url.pathname); let csv = async () => { let url = `/payments`; @@ -128,7 +136,7 @@ } }; - $: showPage = (i) => { + let showPage = $derived((i) => { const currentPage = parseInt(p); const maxVisiblePages = 12; @@ -146,13 +154,13 @@ } return i >= start && i <= end; - }; + }); - $: isEllipsis = (i) => { + let isEllipsis = $derived((i) => { return ( (i === 1 && !showPage(i)) || (i === pages.length - 2 && !showPage(i)) ); - }; + }); </script> <div class="space-y-5"> @@ -241,7 +249,7 @@ {:else if p.type === types.ecash} <img src="/images/cash.png" class="w-12" /> {:else if p.type === types.reconcile} - <iconify-icon icon="ph:scales-bold" width="32" /> + <iconify-icon icon="ph:scales-bold" width="32"></iconify-icon> {:else if p.type === types.bitcoin} <div class="my-auto"> <img @@ -288,7 +296,7 @@ <div class="grid grid-cols-3 w-full text-center text-lg"> {#each Object.keys(incoming) as c} - <span class="text-base text-secondary text-left" /> + <span class="text-base text-secondary text-left"></span> <!-- <span class="text-base text-secondary" --> <!-- >{$t("payments.subtotal")}</span --> <!-- > --> @@ -323,8 +331,8 @@ </div> <div class="flex justify-center"> - <button class="btn !w-auto" on:click={csv}> - <iconify-icon icon="ph:floppy-disk-bold" width="32" /> + <button class="btn !w-auto" onclick={csv}> + <iconify-icon icon="ph:floppy-disk-bold" width="32"></iconify-icon> <div class="my-auto">{$t("payments.export")}</div> </button> </div> diff --git a/src/routes/(app)/qr/[text]/+page.svelte b/src/routes/(app)/qr/[text]/+page.svelte index e1aae854..02a5b718 100644 --- a/src/routes/(app)/qr/[text]/+page.svelte +++ b/src/routes/(app)/qr/[text]/+page.svelte @@ -2,7 +2,7 @@ import Icon from "$comp/Icon.svelte"; import Qr from "$comp/Qr.svelte"; import { back, copy } from "$lib/utils"; - export let data; + let { data } = $props(); let { src, text } = data; </script> @@ -12,9 +12,9 @@ <button type="button" class="btn break-all !h-auto flex-nowrap p-4 font-normal leading-normal" - on:click={() => copy(text)} + onclick={() => copy(text)} > - <iconify-icon icon="ph:copy-bold" width="32" /> + <iconify-icon icon="ph:copy-bold" width="32"></iconify-icon> <div class="my-auto">{text}</div> </button> </div> diff --git a/src/routes/(app)/qr/create/+page.svelte b/src/routes/(app)/qr/create/+page.svelte index fd99a54b..74316ba9 100644 --- a/src/routes/(app)/qr/create/+page.svelte +++ b/src/routes/(app)/qr/create/+page.svelte @@ -1,9 +1,11 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { goto } from "$app/navigation"; import { browser } from "$app/environment"; import { t } from "$lib/translations"; import Icon from "$comp/Icon.svelte"; - let el, text, pasted; + let el = $state(), text = $state(), pasted = $state(); let keypress = (e) => e.key === "Enter" ? e.preventDefault() || el.click() : (pasted = false); @@ -15,7 +17,9 @@ let submit = () => goto(`/qr/${encodeURIComponent(text)}`); - $: if (browser && pasted && text) el.click() && (pasted = false); + run(() => { + if (browser && pasted && text) el.click() && (pasted = false); + }); </script> <div class="container px-4 max-w-lg mx-auto space-y-5 mt-20"> @@ -23,25 +27,25 @@ Create QR </h1> - <form on:submit|preventDefault={submit} class="space-y-2 text-xl"> + <form onsubmit={preventDefault(submit)} class="space-y-2 text-xl"> <div class="mb-2"> <textarea use:focus name="text" placeholder="Enter some text or a URL to put in a QR" - on:keypress={keypress} + onkeypress={keypress} class="w-full p-4 border rounded-xl h-32 text-xl" bind:value={text} - on:paste={() => (pasted = true)} + onpaste={() => (pasted = true)} autocapitalize="none" - /> +></textarea> </div> <div class="flex gap-2"> <button type="button" class="flex border rounded-2xl px-6 py-5 font-bold hover:opacity-80 w-full bg-primary justify-center gap-2" - on:click={paste} + onclick={paste} > <Icon icon="paste" style="w-8 my-auto" /> <div class="my-auto">{$t("user.send.paste")}</div> diff --git a/src/routes/(app)/receive/[...token]/+page.svelte b/src/routes/(app)/receive/[...token]/+page.svelte index 575c8269..3c081fdc 100644 --- a/src/routes/(app)/receive/[...token]/+page.svelte +++ b/src/routes/(app)/receive/[...token]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { page } from "$app/stores"; import { fly } from "svelte/transition"; import { enhance } from "$app/forms"; @@ -9,13 +11,12 @@ import Spinner from "$comp/Spinner.svelte"; import { back, fail, focus } from "$lib/utils"; - export let data; - export let form; + let { data = $bindable(), form } = $props(); let { token } = data; data.subject = data.user; - let el, text, pasted, w; + let el = $state(), text = $state(), pasted = $state(), w = $state(); let keypress = (e) => e.key === "Enter" && (e.preventDefault() || el.click()); @@ -23,7 +24,9 @@ text = await navigator.clipboard.readText(); }; - $: if (browser && pasted && text) el.click() && (pasted = false); + run(() => { + if (browser && pasted && text) el.click() && (pasted = false); + }); </script> <svelte:window bind:innerWidth={w} /> @@ -49,24 +52,24 @@ use:focus name="text" placeholder={$t("payments.voucherText")} - on:keypress={keypress} + onkeypress={keypress} class="w-full p-4 border rounded-xl h-32 text-xl" bind:value={text} - on:paste={() => (pasted = true)} + onpaste={() => (pasted = true)} autocapitalize="none" - /> +></textarea> </div> <div class="flex gap-2"> <a href="/scan" class="contents"> <button type="button" class="btn !w-auto flex-grow"> - <iconify-icon icon="ph:camera-bold" width="32" /> + <iconify-icon icon="ph:camera-bold" width="32"></iconify-icon> <div class="my-auto">{$t("user.send.scan")}</div> </button> </a> - <button type="button" class="btn !w-auto flex-grow" on:click={paste}> - <iconify-icon icon="ph:clipboard-text-bold" width="32" /> + <button type="button" class="btn !w-auto flex-grow" onclick={paste}> + <iconify-icon icon="ph:clipboard-text-bold" width="32"></iconify-icon> <div class="my-auto">{$t("user.send.paste")}</div> </button> </div> diff --git a/src/routes/(app)/reset/[code]/+page.svelte b/src/routes/(app)/reset/[code]/+page.svelte index d93e8bdf..144c73a9 100644 --- a/src/routes/(app)/reset/[code]/+page.svelte +++ b/src/routes/(app)/reset/[code]/+page.svelte @@ -5,10 +5,10 @@ import { fly } from "svelte/transition"; import { password } from "$lib/store"; - export let form; + let { form } = $props(); let email; let loading; - let revealPassword; + let revealPassword = $state(); </script> <div class="pt-10"> @@ -56,7 +56,7 @@ {/if} <button type="button" - on:click={() => (revealPassword = !revealPassword)} + onclick={() => (revealPassword = !revealPassword)} class="absolute right-5 top-10" > <Icon icon={revealPassword ? "eye" : "eye-off"} /> diff --git a/src/routes/(app)/scan/[email protected] b/src/routes/(app)/scan/[email protected] index 2dc061a8..14b35465 100644 --- a/src/routes/(app)/scan/[email protected] +++ b/src/routes/(app)/scan/[email protected] @@ -1,3 +1,11 @@ +<script lang="ts"> + interface Props { + children?: import('svelte').Snippet; + } + + let { children }: Props = $props(); +</script> + <main class="min-h-dvh"> - <slot /> + {@render children?.()} </main> diff --git a/src/routes/(app)/scan/+page.svelte b/src/routes/(app)/scan/+page.svelte index 1acc9b13..edff522e 100644 --- a/src/routes/(app)/scan/+page.svelte +++ b/src/routes/(app)/scan/+page.svelte @@ -6,7 +6,7 @@ import { back } from "$lib/utils"; import { goto } from "$app/navigation"; - let scanner, vid, resizing; + let scanner, vid = $state(), resizing; let resize = () => { if (resizing) clearTimeout(resizing); @@ -31,19 +31,19 @@ onDestroy(() => scanner?.stop()); </script> -<svelte:window on:resize={resize} /> +<svelte:window onresize={resize} /> <div class="flex w-full mb-4 p-4"> <div class="mx-auto rounded-3xl"> <video bind:this={vid} class="border-4 rounded-3xl border-black max-h-[calc(100vh*0.7)]" - /> +></video> </div> </div> <div class="flex justify-center"> - <button class="btn !w-auto" on:click={back}>Cancel</button> + <button class="btn !w-auto" onclick={back}>Cancel</button> </div> <style> diff --git a/src/routes/(app)/send/+layout.svelte b/src/routes/(app)/send/+layout.svelte index 9e14fa39..5c6d8f11 100644 --- a/src/routes/(app)/send/+layout.svelte +++ b/src/routes/(app)/send/+layout.svelte @@ -3,7 +3,7 @@ import Pin from "$comp/Pin.svelte"; import { pin } from "$lib/store"; - export let data; + let { data, children } = $props(); let { user } = data; let cancel = () => goto(`/${user.username}`); @@ -13,4 +13,4 @@ <Pin bind:value={$pin} {cancel} /> {/if} -<slot /> +{@render children?.()} diff --git a/src/routes/(app)/send/[...text]/+page.svelte b/src/routes/(app)/send/[...text]/+page.svelte index 2dd4a723..7ec76bc9 100644 --- a/src/routes/(app)/send/[...text]/+page.svelte +++ b/src/routes/(app)/send/[...text]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { page } from "$app/stores"; import { fly } from "svelte/transition"; import { enhance } from "$app/forms"; @@ -10,13 +12,12 @@ import Spinner from "$comp/Spinner.svelte"; import { back, fail, focus } from "$lib/utils"; - export let data; - export let form; + let { data = $bindable(), form } = $props(); data.subject = data.user; let { contacts } = data; - let el, text, pasted, w; + let el = $state(), text = $state(), pasted = $state(), w = $state(); let keypress = (e) => e.key === "Enter" ? e.preventDefault() || el.click() : (pasted = false); @@ -27,7 +28,9 @@ pasted = true; }; - $: if (browser && pasted && text) el.click() && (pasted = false); + run(() => { + if (browser && pasted && text) el.click() && (pasted = false); + }); </script> <svelte:window bind:innerWidth={w} /> @@ -52,29 +55,29 @@ use:focus name="text" placeholder={$t("user.send.placeholder")} - on:keypress={keypress} + onkeypress={keypress} class="w-full p-4 border rounded-xl h-32 text-xl" bind:value={text} - on:paste={() => (pasted = true)} + onpaste={() => (pasted = true)} autocapitalize="none" - /> +></textarea> <div class="flex gap-2"> <a href="/scan" class="contents"> <button type="button" class="btn !w-auto flex-grow"> - <iconify-icon icon="ph:camera-bold" width="32" /> + <iconify-icon icon="ph:camera-bold" width="32"></iconify-icon> {$t("user.send.scan")} </button> </a> - <button type="button" class="btn !w-auto flex-grow" on:click={paste}> - <iconify-icon icon="ph:clipboard-text-bold" width="32" /> + <button type="button" class="btn !w-auto flex-grow" onclick={paste}> + <iconify-icon icon="ph:clipboard-text-bold" width="32"></iconify-icon> {$t("user.send.paste")} </button> </div> <button bind:this={el} type="submit" class="btn btn-accent"> - <iconify-icon icon="ph:paper-plane-right-bold" width="32" /> + <iconify-icon icon="ph:paper-plane-right-bold" width="32"></iconify-icon> <div class="my-auto">{$t("user.send.next")}</div> </button> diff --git a/src/routes/(app)/send/bitcoin/[address]/+page.svelte b/src/routes/(app)/send/bitcoin/[address]/+page.svelte index 20fed58a..c271543c 100644 --- a/src/routes/(app)/send/bitcoin/[address]/+page.svelte +++ b/src/routes/(app)/send/bitcoin/[address]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { t } from "$lib/translations"; import Icon from "$comp/Icon.svelte"; import Numpad from "$comp/Numpad.svelte"; @@ -6,22 +8,24 @@ import { rate } from "$lib/store"; import { fail, s } from "$lib/utils"; - export let data; + let { data } = $props(); let { balance, rates, user } = data; let { address } = $page.params; let { currency, username } = user; - let amount = 0; - let submit, fiat; + let amount = $state(0); + let submit = $state(), fiat = $state(); - $: update(data); let update = () => ($rate = data.rates[currency]); let setMax = () => { fiat = false; amount = balance; }; + run(() => { + update(data); + }); </script> <div class="container px-4 max-w-xl mx-auto space-y-5 text-center"> @@ -35,8 +39,8 @@ <button type="button" class="btn !w-auto grow" - on:click|preventDefault={setMax} - on:keydown={setMax}>Max ⚡️{s(balance)}</button + onclick={preventDefault(setMax)} + onkeydown={setMax}>Max ⚡️{s(balance)}</button > <form action={`/send/bitcoin/${address}/${amount}`} class="contents"> diff --git a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte index 15080493..20128d2b 100644 --- a/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte +++ b/src/routes/(app)/send/bitcoin/[address]/[amount]/[...feeRate]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { tick } from "svelte"; import { t } from "$lib/translations"; import { enhance } from "$app/forms"; @@ -28,14 +30,13 @@ import { entropyToMnemonic, mnemonicToSeed } from "@scure/bip39"; import { wordlist } from "@scure/bip39/wordlists/english"; - export let data; - export let form; + let { data, form } = $props(); let { encode, decode } = hexUtil; - let passwordPrompt; - let password; - let cancel = () => (passwordPrompt = false); - let signed; + let passwordPrompt = $state(); + let password = $state(); + let cancel = $state(() => (passwordPrompt = false)); + let signed = $state(); let togglePassword = () => (passwordPrompt = !passwordPrompt); let handler = ({ cancel }) => { @@ -90,9 +91,8 @@ rates, hex, inputs, - } = data; + } = $state(data); - $: reload(data); let reload = () => { ({ amount, address, message, fee, fees, feeRate, ourfee, rates, hex } = data); @@ -103,7 +103,7 @@ }; let { balance, currency } = data.user; - let submitting, submit, showSettings; + let submitting = $state(), submit = $state(), showSettings; let feeNames = { fastestFee: $t("payments.fastest"), @@ -113,7 +113,6 @@ let toggleSettings = () => (showSettings = !showSettings); - $: update(form); let update = () => { submitting = false; if (form?.message?.includes("pin")) $pin = undefined; @@ -121,6 +120,12 @@ let setFee = () => goto(`/send/bitcoin/${address}/${amount}/${feeRate}`); let goBack = () => goto(`/send/bitcoin/${address}`); + run(() => { + reload(data); + }); + run(() => { + update(form); + }); </script> <div @@ -148,7 +153,7 @@ <div class="flex flex-wrap gap-4 justify-center"> <select bind:value={feeRate} - on:change={setFee} + onchange={setFee} class="border text-lg bg-white p-4 rounded-2xl text-center my-auto" > {#each Object.keys(feeNames) as feeName} diff --git a/src/routes/(app)/send/ecash/+page.svelte b/src/routes/(app)/send/ecash/+page.svelte index 3a708f80..88239c1a 100644 --- a/src/routes/(app)/send/ecash/+page.svelte +++ b/src/routes/(app)/send/ecash/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { enhance, applyAction } from "$app/forms"; import { t } from "$lib/translations"; import Icon from "$comp/Icon.svelte"; @@ -9,15 +11,14 @@ import { fail, s } from "$lib/utils"; import handler from "$lib/handler"; - export let data; + let { data } = $props(); let { rates, user } = data; let { balance, currency, username } = user; - let amount = 0; - let submit, fiat; + let amount = $state(0); + let submit = $state(), fiat = $state(); - $: update(data); let update = () => ($rate = data.rates[currency]); let setMax = () => { @@ -25,8 +26,11 @@ amount = balance; }; - let submitting; + let submitting = $state(); let toggle = () => (submitting = !submitting); + run(() => { + update(data); + }); </script> <div class="container px-4 max-w-xl mx-auto space-y-5 text-center"> @@ -47,9 +51,9 @@ <button type="button" class="btn !w-auto grow" - on:click|preventDefault={setMax} + onclick={preventDefault(setMax)} disabled={submitting} - on:keydown={setMax}>Max ⚡️{s(balance)}</button + onkeydown={setMax}>Max ⚡️{s(balance)}</button > <button diff --git a/src/routes/(app)/send/fund/[name]/[...amount]/+page.svelte b/src/routes/(app)/send/fund/[name]/[...amount]/+page.svelte index b6a4aa0c..d1c3b204 100644 --- a/src/routes/(app)/send/fund/[name]/[...amount]/+page.svelte +++ b/src/routes/(app)/send/fund/[name]/[...amount]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { t } from "$lib/translations"; import { enhance } from "$app/forms"; import Icon from "$comp/Icon.svelte"; @@ -8,25 +10,29 @@ import { back } from "$lib/utils"; import { pin } from "$lib/store"; - export let data; - export let form; + let { data, form } = $props(); - let { amount, name } = $page.params; + let { amount, name } = $state($page.params); let { rates } = data; let { currency } = data.user; - let loading; + let loading = $state(); - $: rate = rates[currency]; let submit = () => (loading = true); - $: update(form); let update = () => { if (form?.message?.includes("pin")) $pin = undefined; loading = false; }; + let rate; + run(() => { + rate = rates[currency]; + }); + run(() => { + update(form); + }); </script> -<button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" on:click={back}> +<button class="ml-5 md:ml-20 mt-5 md:mt-10 hover:opacity-80" onclick={back}> <Icon icon="arrow-left" style="w-10" /> </button> @@ -39,7 +45,7 @@ <div class="container px-4 mt-20 max-w-xl mx-auto"> <Numpad bind:amount {currency} bind:rate /> - <form method="POST" use:enhance on:submit={submit}> + <form method="POST" use:enhance onsubmit={submit}> <input name="name" value={name} type="hidden" /> <input name="amount" value={amount} type="hidden" /> <input name="pin" value={$pin} type="hidden" /> diff --git a/src/routes/(app)/send/invoice/[id]/+page.svelte b/src/routes/(app)/send/invoice/[id]/+page.svelte index 5a9729a2..9f3a008b 100644 --- a/src/routes/(app)/send/invoice/[id]/+page.svelte +++ b/src/routes/(app)/send/invoice/[id]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import handler from "$lib/handler"; import { onDestroy, onMount } from "svelte"; import { t } from "$lib/translations"; @@ -21,34 +23,31 @@ sats, focus, } from "$lib/utils"; - export let data; - export let form; + let { data, form } = $props(); - let { invoice, rates, user } = data; - let { address, hash, payreq, user: recipient, tip } = invoice; - let { currency } = user; + let { invoice, rates, user } = $state(data); + let { address, hash, payreq, user: recipient, tip } = $state(invoice); + let { currency } = $state(user); - $: reload(data); let reload = (data) => { ({ invoice, rates, user } = data); ({ address, hash, payreq, user: recipient, tip } = invoice); ({ currency } = user); }; - $: rate = invoice.rate * (rates[user.currency] / rates[invoice.currency]); - let amount = form?.amount || invoice.amount; - let a, - af, + let amount = $state(form?.amount || invoice.amount); + let a = $state(), + af = $state(), amountFiat = amount * (rate / sats), - fiat = !amount; + fiat = $state(!amount); let setAmount = () => { amount = a; amountFiat = af; }; - let submit, submitting; + let submit = $state(), submitting = $state(); let toggle = () => (submitting = !submitting); let external = async () => { @@ -67,7 +66,6 @@ }); }; - $: update(form); let update = () => { if (form?.message?.includes("pin")) $pin = undefined; submitting = false; @@ -91,6 +89,16 @@ // } // } // }); + run(() => { + reload(data); + }); + let rate; + run(() => { + rate = invoice.rate * (rates[user.currency] / rates[invoice.currency]); + }); + run(() => { + update(form); + }); </script> {#if form?.message} @@ -192,13 +200,13 @@ bind:this={submit} type="button" class="btn !w-auto" - on:click={setAmount} + onclick={setAmount} > {$t("payments.next")} </button> {/if} </div> - <button type="button" class="btn" on:click={external} + <button type="button" class="btn" onclick={external} >{$t("payments.moreOptions")}</button > </form> diff --git a/src/routes/(app)/send/lightning/[payreq]/+page.svelte b/src/routes/(app)/send/lightning/[payreq]/+page.svelte index 659b0e51..6b9fe4e2 100644 --- a/src/routes/(app)/send/lightning/[payreq]/+page.svelte +++ b/src/routes/(app)/send/lightning/[payreq]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from "svelte/legacy"; + import { t } from "$lib/translations"; import { enhance } from "$app/forms"; import Icon from "$comp/Icon.svelte"; @@ -8,8 +10,7 @@ import { back, fiat, f, s, focus } from "$lib/utils"; import { rate, pin } from "$lib/store"; - export let data; - export let form; + let { data, form } = $props(); let { payreq } = $page.params; let { @@ -17,10 +18,9 @@ ourfee, rates, user: { currency }, - } = data; - let a; + } = $state(data); + let a = $state(); - $: reload(data); let reload = (data) => { ({ alias, @@ -31,13 +31,10 @@ if (!$rate) $rate = rates[currency]; }; - $: amount = form?.amount || data.amount; - $: maxfee = Math.max(5, Math.round(amount * 0.005)); - let showMax; + let showMax = $state(); - let loading; + let loading = $state(); let submit = () => (loading = true); - $: update(form); let update = () => { if (form?.message?.includes("pin")) $pin = undefined; loading = false; @@ -45,6 +42,17 @@ let show; let toggle = () => (show = !show); + run(() => { + reload(data); + }); + let amount = $derived(form?.amount || data.amount); + let maxfee; + run(() => { + maxfee = Math.max(5, Math.round(amount * 0.005)); + }); + run(() => { + update(form); + }); </script> <div class="container px-4 max-w-xl mx-auto text-center space-y-2"> @@ -89,7 +97,7 @@ <form method="POST" use:enhance - on:submit={submit} + onsubmit={submit} action="?/send" class="space-y-2" > @@ -135,7 +143,7 @@ </button> {#if !(form?.message || showMax)} - <button type="button" class="btn" on:click={() => (showMax = !showMax)} + <button type="button" class="btn" onclick={() => (showMax = !showMax)} >Advanced settings</button > <input name="maxfee" type="hidden" bind:value={maxfee} /> diff --git a/src/routes/(app)/sent/[id]/+page.svelte b/src/routes/(app)/sent/[id]/+page.svelte index b4f6ab68..615638c7 100644 --- a/src/routes/(app)/sent/[id]/+page.svelte +++ b/src/routes/(app)/sent/[id]/+page.svelte @@ -5,8 +5,8 @@ import { toast } from "@zerodevx/svelte-toast"; import { t } from "$lib/translations"; - export let data; - let { amount, rate, tip, user } = data; + let { data } = $props(); + let { amount, rate, tip, user } = $state(data); let { currency, username } = user; amount = Math.abs(amount); @@ -38,7 +38,7 @@ </div> <a href={`/${username}`} use:focus> - <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50" /> + <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50"></div> </a> <div class="flex justify-center"> diff --git a/src/routes/(app)/settings/[...tab]/+page.svelte b/src/routes/(app)/settings/[...tab]/+page.svelte index d2da3722..5b9e048d 100644 --- a/src/routes/(app)/settings/[...tab]/+page.svelte +++ b/src/routes/(app)/settings/[...tab]/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { browser } from "$app/environment"; import { onMount, tick } from "svelte"; import { fly } from "svelte/transition"; @@ -22,24 +24,20 @@ import { PUBLIC_COINOS_URL } from "$env/static/public"; - export let data; - export let form; + let { data, form } = $props(); - let submit; - let formElement; + let submit = $state(); + let formElement = $state(); - let { user, token, rates, tab, cookies, subscriptions } = data; + let { user, token, rates, tab, cookies, subscriptions } = $state(data); let prev; - $: update(data); let update = () => { ({ user, token, rates, tab, subscriptions } = data); prev = { ...user }; }; - $: form?.user && ({ user } = form); - $: form?.success && throttledSuccess(); let justUpdated; let throttledSuccess = () => { @@ -50,12 +48,7 @@ } }; - $: form?.message && fail(form.message); - $: if (form?.message?.startsWith("Pin")) { - fail("Wrong pin, try again"); - $pin = ""; - } let tabs = [ { name: "account", key: "ACCOUNT", comp: Account }, @@ -64,13 +57,10 @@ { name: "shopify", key: "SHOPIFY", comp: Shopify }, ]; - $: ({ comp } = tabs.find((t) => t.name === tab)); let { address, id, username } = user; - let submitting; + let submitting = $state(); - $: if (!$loading && $page.url.searchParams.get("verified")) - success($t("user.settings.verified")); async function handleSubmit() { try { @@ -191,6 +181,31 @@ submitting = false; } + run(() => { + update(data); + }); + run(() => { + form?.user && ({ user } = form); + }); + run(() => { + form?.success && throttledSuccess(); + }); + run(() => { + form?.message && fail(form.message); + }); + run(() => { + if (form?.message?.startsWith("Pin")) { + fail("Wrong pin, try again"); + $pin = ""; + } + }); + let { comp } = $derived(tabs.find((t) => t.name === tab)); + run(() => { + if (!$loading && $page.url.searchParams.get("verified")) + success($t("user.settings.verified")); + }); + + const SvelteComponent = $derived(comp); </script> {#if user.haspin && $pin?.length !== 6} @@ -200,7 +215,7 @@ <form method="POST" class="mb-[154px] settings" - on:submit|preventDefault={handleSubmit} + onsubmit={preventDefault(handleSubmit)} bind:this={formElement} > <input type="hidden" name="pin" value={$pin} /> @@ -229,7 +244,7 @@ </div> </div> - <svelte:component this={comp} {user} {rates} {submit} {subscriptions} /> + <SvelteComponent {user} {rates} {submit} {subscriptions} /> </div> <div diff --git a/src/routes/(app)/settings/[...tab]/_account.svelte b/src/routes/(app)/settings/[...tab]/_account.svelte index 8537322e..54249265 100644 --- a/src/routes/(app)/settings/[...tab]/_account.svelte +++ b/src/routes/(app)/settings/[...tab]/_account.svelte @@ -4,11 +4,11 @@ import { t } from "$lib/translations"; import { page } from "$app/stores"; - export let user, rates, submit; + let { user = $bindable(), rates, submit } = $props(); let { id } = user; - let avatarFile, avatarInput, bannerFile, bannerInput; + let avatarFile, avatarInput = $state(), bannerFile, bannerInput = $state(); let selectAvatar = () => avatarInput.click(); let selectBanner = () => bannerInput.click(); @@ -18,7 +18,7 @@ percent = Math.round((event.loaded / event.total) * 100); }; - let tooLarge = {}; + let tooLarge = $state({}); let handleFile = async ({ target }, type) => { tooLarge[type] = false; @@ -47,9 +47,9 @@ if (!user.display) user.display = user.username; - $: url = `${$page.url.host}/${user.username}`; - $: full = `${$page.url.protocol}//${url}`; - $: addr = `${user.username}@${$page.url.host}`; + let url = $derived(`${$page.url.host}/${user.username}`); + let full = $derived(`${$page.url.protocol}//${url}`); + let addr = $derived(`${user.username}@${$page.url.host}`); </script> <div> @@ -83,13 +83,13 @@ icon="ph:check-bold" class="text-success ml-auto" width="32" - /> +></iconify-icon> {:else if user.email} <iconify-icon icon="ph:clock-bold" class="text-warning ml-auto" width="32" - /> +></iconify-icon> {/if} </label> </div> @@ -101,8 +101,8 @@ {#if $avatar || user.profile} <div class="relative rounded-full overflow-hidden text-center w-20 h-20 my-auto hover:opacity-80 cursor-pointer" - on:click={selectAvatar} - on:keydown={selectAvatar} + onclick={selectAvatar} + onkeydown={selectAvatar} > <img src={$avatar?.src || `/api/public/${user.profile}.webp`} @@ -113,11 +113,11 @@ {:else} <div class="rounded-full border-4 border-white p-4 bg-gradient-to-r from-primary to-gradient w-24 my-auto hover:opacity-80 cursor-pointer" - on:click={selectAvatar} - on:keydown={selectAvatar} + onclick={selectAvatar} + onkeydown={selectAvatar} > <Icon icon="logo-symbol-white" style="mx-auto" /> - <iconify-icon icon="ph:floppy-disk-bold" width="32" /> + <iconify-icon icon="ph:floppy-disk-bold" width="32"></iconify-icon> </div> {/if} <div class="ml-2 p-2"> @@ -125,14 +125,14 @@ <button type="button" class="btn" - on:click={selectAvatar} - on:keydown={selectAvatar}>{$t("user.settings.select")}</button + onclick={selectAvatar} + onkeydown={selectAvatar}>{$t("user.settings.select")}</button > <input type="file" class="hidden" bind:this={avatarInput} - on:change={(e) => handleFile(e, "profile")} + onchange={(e) => handleFile(e, "profile")} /> </div> </div> @@ -151,30 +151,30 @@ <img src={$banner ? $banner.src : `/api/public/${user.banner}.webp`} class="w-full object-cover object-center visible overflow-hidden h-48 mb-4 hover:opacity-80" - on:click={selectBanner} - on:keydown={selectBanner} + onclick={selectBanner} + onkeydown={selectBanner} alt="Banner" /> {:else} <div class="bg-gradient-to-r from-primary to-gradient w-full h-48 mb-4 cursor-pointer hover:opacity-80" - on:click={selectBanner} - on:keydown={selectBanner} + onclick={selectBanner} + onkeydown={selectBanner} alt="Banner" - /> +></div> {/if} <button type="button" class="btn !w-auto" - on:click={selectBanner} - on:keydown={selectBanner}>{$t("user.settings.select")}</button + onclick={selectBanner} + onkeydown={selectBanner}>{$t("user.settings.select")}</button > <input type="file" class="hidden" bind:this={bannerInput} - on:change={(e) => handleFile(e, "banner")} + onchange={(e) => handleFile(e, "banner")} /> {#if tooLarge["banner"]} @@ -191,5 +191,5 @@ name="address" bind:value={user.address} placeholder={$t("user.settings.aboutPlaceholder")} - /> +></textarea> </div> diff --git a/src/routes/(app)/settings/[...tab]/_pos.svelte b/src/routes/(app)/settings/[...tab]/_pos.svelte index f4a01c09..3f68eebc 100644 --- a/src/routes/(app)/settings/[...tab]/_pos.svelte +++ b/src/routes/(app)/settings/[...tab]/_pos.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { onMount, tick } from "svelte"; import { browser } from "$app/environment"; import Numpad from "$comp/Numpad.svelte"; @@ -9,16 +11,20 @@ import { page } from "$app/stores"; import { PUBLIC_VAPID_PUBKEY } from "$env/static/public"; - export let user, rates, submit, subscriptions; + let { + user = $bindable(), + rates, + submit, + subscriptions + } = $props(); - let { currency } = user; - let rate = rates[currency]; + let { currency } = $state(user); + let rate = $state(rates[currency]); let fiats = Object.keys(rates).sort((a, b) => a.localeCompare(b)); - $: user.language = $locale; let keypress = (e) => e.key === "Enter" && (e.preventDefault() || el.click()); - let editingReserve, editingThreshold, doneReserve, doneThreshold; + let editingReserve = $state(), editingThreshold = $state(), doneReserve = $state(), doneThreshold; let doneEditing = () => { editingReserve = false; editingThreshold = false; @@ -38,9 +44,9 @@ if (!user.threshold) user.threshold = 1000000; if (!user.reserve) user.reserve = 100000; - let reserveEl, thresholdEl; + let reserveEl = $state(), thresholdEl = $state(); - let push, pm, subscription; + let push = $state(), pm, subscription; onMount(async () => { if (!browser) return; @@ -60,8 +66,7 @@ } }); - let permission; - $: updateNotifications(push); + let permission = $state(); let updateNotifications = async (push) => { if (!browser || !pm) return (push = false); @@ -80,6 +85,12 @@ await post("/subscription", { subscription }); } }; + run(() => { + user.language = $locale; + }); + run(() => { + updateNotifications(push); + }); </script> <div> @@ -154,17 +165,17 @@ <textarea name="destination" placeholder={$t("user.settings.destinationPlaceholder")} - on:keypress={keypress} + onkeypress={keypress} class="w-full p-4 border rounded-xl h-48" bind:value={user.destination} - /> +></textarea> </div> <div> <label for="display" class="font-bold mb-1 block" >{$t("user.settings.threshold")}</label > - <button type="button" class="flex w-full" on:click={editThreshold}> + <button type="button" class="flex w-full" onclick={editThreshold}> <div class="p-4 border rounded-2xl rounded-r-none border-r-0 bg-base-200"> ⚡️ </div> @@ -184,7 +195,7 @@ <label for="display" class="font-bold mb-1 block" >{$t("user.settings.reserve")}</label > - <button type="button" class="flex w-full" on:click={editReserve}> + <button type="button" class="flex w-full" onclick={editReserve}> <div class="p-4 border rounded-2xl rounded-r-none border-r-0 bg-base-200"> ⚡️ </div> @@ -220,7 +231,7 @@ <button bind:this={doneReserve} type="button" - on:click={doneEditing} + onclick={doneEditing} class="btn">Ok</button > </div> @@ -247,7 +258,7 @@ <button bind:this={doneReserve} type="button" - on:click={doneEditing} + onclick={doneEditing} class="btn">Ok</button > </div> diff --git a/src/routes/(app)/settings/[...tab]/_security.svelte b/src/routes/(app)/settings/[...tab]/_security.svelte index d67bda37..8bb8a3fa 100644 --- a/src/routes/(app)/settings/[...tab]/_security.svelte +++ b/src/routes/(app)/settings/[...tab]/_security.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { getMnemonic, getNsec } from "$lib/nostr"; import { tick } from "svelte"; import { t } from "$lib/translations"; @@ -10,26 +12,26 @@ import { invalidate } from "$app/navigation"; import { page } from "$app/stores"; - export let user, rates, submit; + let { user = $bindable(), rates, submit } = $props(); - let confirming2fa, - disabling2fa, - importing, + let confirming2fa = $state(), + disabling2fa = $state(), + importing = $state(), locked, mnemonic, - newNsec, - nsec, + newNsec = $state(), + nsec = $state(), old, - otp, - password, - pin, - revealPassword, + otp = $state(), + password = $state(), + pin = $state(), + revealPassword = $state(), revealSeed, - revealNsec, - token = "", - setting2fa, - settingPin, - verify; + revealNsec = $state(), + token = $state(""), + setting2fa = $state(), + settingPin = $state(), + verify = $state(); let toggleImporting = () => { revealNsec = false; @@ -56,8 +58,6 @@ } }; - $: verifying = pin?.length > 5; - $: verify && checkPin(pin); let checkPin = async () => { old = $current; @@ -88,7 +88,7 @@ return true; }; - let disablingPin = false; + let disablingPin = $state(false); let togglePin = async () => { if (user.haspin) { @@ -129,7 +129,6 @@ disabling2fa = false; }; - $: enable2fa(token); let enable2fa = async (twoFa) => { try { if (setting2fa && token.length === 6) { @@ -143,7 +142,6 @@ } }; - $: disable2fa(token); let disable2fa = async () => { try { if (disabling2fa && token.length === 6) { @@ -157,6 +155,19 @@ fail("Failed to disable 2FA, try again"); } }; + let verifying; + run(() => { + verifying = pin?.length > 5; + }); + run(() => { + verify && checkPin(pin); + }); + run(() => { + enable2fa(token); + }); + run(() => { + disable2fa(token); + }); </script> <input type="hidden" name="newpin" value={disablingPin ? "delete" : pin} /> @@ -173,14 +184,14 @@ {/if} <button type="button" - on:click={togglePassword} - on:keydown={togglePassword} + onclick={togglePassword} + onkeydown={togglePassword} class="absolute right-5 top-11" > <iconify-icon icon={revealPassword ? "ph:eye-bold" : "ph:eye-slash-bold"} width="32" - /> +></iconify-icon> </button> </div> @@ -203,12 +214,12 @@ notify={false} /> {:else} - <button type="button" class="btn" on:click={togglePin} + <button type="button" class="btn" onclick={togglePin} > <iconify-icon icon={user.haspin ? "ph:lock-key-open-bold" : "ph:lock-key-bold"} width="32" - /> +></iconify-icon> {user.haspin ? $t("user.settings.disablePIN") : $t("user.settings.enablePIN")}</button @@ -232,18 +243,18 @@ <b>{otp.secret}</b> </div> - <button type="button" class="btn" on:click={startConfirming2fa}> - <iconify-icon icon="ph:numpad-bold" width="32" /> + <button type="button" class="btn" onclick={startConfirming2fa}> + <iconify-icon icon="ph:numpad-bold" width="32"></iconify-icon> <div class="my-auto">Confirm</div> </button> {:else if user.twofa} - <button type="button" class="btn" on:click={startDisabling2fa}> - <iconify-icon icon="ph:device-mobile-bold" width="32" /> + <button type="button" class="btn" onclick={startDisabling2fa}> + <iconify-icon icon="ph:device-mobile-bold" width="32"></iconify-icon> <div class="my-auto">{$t("user.settings.twofaDisable")}</div> </button> {:else} - <button type="button" class="btn" on:click={startEnabling2fa}> - <iconify-icon icon="ph:device-mobile-bold" width="32" /> + <button type="button" class="btn" onclick={startEnabling2fa}> + <iconify-icon icon="ph:device-mobile-bold" width="32"></iconify-icon> <div class="my-auto">{$t("user.settings.twofaSetup")}</div> </button> {/if} @@ -269,12 +280,12 @@ </p> <div class="flex gap-2"> - <button type="button" class="btn !w-auto flex-grow" on:click={toggleNsec}> + <button type="button" class="btn !w-auto flex-grow" onclick={toggleNsec}> {#if revealNsec} - <iconify-icon icon="ph:eye-slash-bold" width="32" /> + <iconify-icon icon="ph:eye-slash-bold" width="32"></iconify-icon> {$t("user.settings.hideNsec")} {:else} - <iconify-icon icon="ph:warning-bold" width="32" /> + <iconify-icon icon="ph:warning-bold" width="32"></iconify-icon> {$t("user.settings.revealNsec")} {/if} </button> @@ -282,9 +293,9 @@ <button type="button" class="btn !w-auto flex-grow" - on:click={toggleImporting} + onclick={toggleImporting} > - <iconify-icon icon="ph:floppy-disk-bold" width="32" /> + <iconify-icon icon="ph:floppy-disk-bold" width="32"></iconify-icon> {$t("user.settings.import")} </button> </div> @@ -298,8 +309,8 @@ {nsec} </div> - <button type="button" class="btn" on:click={() => copy(nsec)}> - <iconify-icon icon="ph:copy-bold" width="32" /> + <button type="button" class="btn" onclick={() => copy(nsec)}> + <iconify-icon icon="ph:copy-bold" width="32"></iconify-icon> Copy </button> {/if} diff --git a/src/routes/(app)/settings/[...tab]/_shopify.svelte b/src/routes/(app)/settings/[...tab]/_shopify.svelte index 48fe7718..cc746c49 100644 --- a/src/routes/(app)/settings/[...tab]/_shopify.svelte +++ b/src/routes/(app)/settings/[...tab]/_shopify.svelte @@ -3,22 +3,22 @@ import Icon from "$comp/Icon.svelte"; import { page } from "$app/stores"; - export let user; - $: paymentsUrl = - user.shopifyStore && + let { user = $bindable() } = $props(); + let paymentsUrl = + $derived(user.shopifyStore && "https://admin.shopify.com/store/" + user.shopifyStore + - "/settings/payments"; - $: checkoutUrl = - user.shopifyStore && + "/settings/payments"); + let checkoutUrl = + $derived(user.shopifyStore && "https://admin.shopify.com/store/" + user.shopifyStore + - "/settings/checkout"; - $: appsUrl = - user.shopifyStore && + "/settings/checkout"); + let appsUrl = + $derived(user.shopifyStore && "https://admin.shopify.com/store/" + user.shopifyStore + - "/settings/apps/development"; + "/settings/apps/development"); let script = `<script src="${$page.url.protocol}//${$page.url.host}/${user.username}/shopify.js"><\/script>`; </script> diff --git a/src/routes/(app)/verify/[code]/+page.svelte b/src/routes/(app)/verify/[code]/+page.svelte index de5212e5..1fe5d898 100644 --- a/src/routes/(app)/verify/[code]/+page.svelte +++ b/src/routes/(app)/verify/[code]/+page.svelte @@ -3,7 +3,7 @@ import Icon from "$comp/Icon.svelte"; import { t } from "$lib/translations"; - export let data; + let { data } = $props(); let { user, error } = data; </script> @@ -27,7 +27,7 @@ </div> <a href={`/${user.username}`}> - <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50" /> + <div class="opacity-0 w-screen h-screen fixed top-0 left-0 z-50"></div> </a> <div class="flex justify-center"> diff --git a/src/routes/(static)/+layout.svelte b/src/routes/(static)/+layout.svelte index c9bdc091..44310c97 100644 --- a/src/routes/(static)/+layout.svelte +++ b/src/routes/(static)/+layout.svelte @@ -1,13 +1,17 @@ <script> + import { run } from 'svelte/legacy'; + import { SvelteToast } from "@zerodevx/svelte-toast"; import Footer from "$comp/Footer.svelte"; import LandingHeader from "$comp/LandingHeader.svelte"; import { theme as themeStore } from "$lib/store"; - export let data; - let { theme } = data; - $: ({ user } = data); - $: theme = $themeStore; + let { data, children } = $props(); + let { theme } = $state(data); + let { user } = $derived(data); + run(() => { + theme = $themeStore; + }); </script> <SvelteToast options={{ reversed: true, intro: { y: 192 } }} /> @@ -16,6 +20,6 @@ class="container flex px-4 md:px-40 mx-auto min-h-[600px]" data-theme={theme} > - <slot /> + {@render children?.()} </main> <Footer /> diff --git a/src/routes/(static)/docs/+page.svelte b/src/routes/(static)/docs/+page.svelte index f83ba8c0..9f724484 100644 --- a/src/routes/(static)/docs/+page.svelte +++ b/src/routes/(static)/docs/+page.svelte @@ -5,7 +5,7 @@ import Code from "$comp/Code.svelte"; import Icon from "$comp/Icon.svelte"; - export let data; + let { data } = $props(); let { user, token } = data; @@ -40,7 +40,7 @@ <h2 class="text-2xl">API Base URL</h2> <div class="bg-primary text-primary-content rounded-lg p-4 flex gap-4"> <div>{api}</div> - <button class="ml-auto my-auto invert opacity-90" on:click={() => copy(api)} + <button class="ml-auto my-auto invert opacity-90" onclick={() => copy(api)} ><Icon icon="copy" style="w-10 max-w-none" /></button > </div> @@ -61,7 +61,7 @@ <div class="w-full break-all">{tokenSample}</div> <button class="ml-auto my-auto invert opacity-90" - on:click={() => copy(tokenSample)} + onclick={() => copy(tokenSample)} ><Icon icon="copy" style="w-10 max-w-none" /></button > </div> diff --git a/src/routes/(static)/login/+page.svelte b/src/routes/(static)/login/+page.svelte index f51a24eb..d50e0cdc 100644 --- a/src/routes/(static)/login/+page.svelte +++ b/src/routes/(static)/login/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import { onMount } from "svelte"; import { applyAction, deserialize } from "$app/forms"; import { tick } from "svelte"; @@ -23,28 +25,24 @@ if (lang) document.cookie = `lang=${lang} ;`; }); - export let form; + let { form } = $props(); - let token, formElement; + let token = $state(), formElement; let code = []; let redirect; $password = undefined; - $: need2fa = form?.message === "2fa"; let cancel = () => (need2fa = false); - $: if (form?.message === "2fa" && form.token === token) token = ""; - let username, email, btn; + let username = $state(), email, btn = $state(); - $: update(form); let update = (form) => form && ({ username, password: $password } = form); - $: token && token?.length === 6 && tick().then(() => btn.click()); - let revealPassword = false; + let revealPassword = $state(false); - let loading; + let loading = $state(); async function handleSubmit(e) { loading = true; @@ -69,6 +67,19 @@ applyAction(result); loading = false; } + let need2fa; + run(() => { + need2fa = form?.message === "2fa"; + }); + run(() => { + if (form?.message === "2fa" && form.token === token) token = ""; + }); + run(() => { + update(form); + }); + run(() => { + token && token?.length === 6 && tick().then(() => btn.click()); + }); </script> {#if need2fa} @@ -86,7 +97,7 @@ </div> {/if} - <form class="space-y-5" on:submit|preventDefault={handleSubmit} method="POST"> + <form class="space-y-5" onsubmit={preventDefault(handleSubmit)} method="POST"> <input type="hidden" name="loginRedirect" @@ -131,10 +142,10 @@ {/if} <iconify-icon class="cursor-pointer ml-auto" - on:click={() => (revealPassword = !revealPassword)} + onclick={() => (revealPassword = !revealPassword)} icon={revealPassword ? "ph:eye-bold" : "ph:eye-slash-bold"} width="32" - /> +></iconify-icon> </label> <div class="flex justify-end items-center"> diff --git a/src/routes/(static)/register/+page.svelte b/src/routes/(static)/register/+page.svelte index fe9a4aa2..c179552c 100644 --- a/src/routes/(static)/register/+page.svelte +++ b/src/routes/(static)/register/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run, preventDefault } from 'svelte/legacy'; + import punks from "$lib/punks"; import { upload } from "$lib/upload"; import { afterNavigate, invalidateAll } from "$app/navigation"; @@ -23,12 +25,10 @@ animals, } from "unique-names-generator"; - export let form; - export let data; + let { form = $bindable(), data } = $props(); - $: data && ($avatar = undefined); - let username; - let { index } = data; + let username = $state(); + let { index } = $state(data); let cleared; let clear = () => { @@ -64,24 +64,20 @@ } }); - let token, formElement; + let token = $state(), formElement; let code = []; let redirect; - $: need2fa = form?.message === "2fa"; let cancel = () => (need2fa = false); - $: if (form?.message === "2fa" && form.token === token) token = ""; - let email, btn; + let email, btn = $state(); - $: update(form); let update = (form) => form && ({ username, password: $password } = form); - $: token && token?.length === 6 && tick().then(() => btn.click()); - let revealPassword; + let revealPassword = $state(); - let loading; + let loading = $state(); async function handleSubmit(e) { loading = true; @@ -127,8 +123,7 @@ loading = false; } - let avatarInput; - $: src = `/api/public/${punks[index]}.webp`; + let avatarInput = $state(); let decr = () => (index = index <= 0 ? 63 : index - 1); let incr = () => (index = index >= 63 ? 0 : index + 1); let selectAvatar = () => avatarInput.click(); @@ -149,6 +144,26 @@ reader.readAsDataURL(file); }; + run(() => { + data && ($avatar = undefined); + }); + let need2fa; + run(() => { + need2fa = form?.message === "2fa"; + }); + run(() => { + if (form?.message === "2fa" && form.token === token) token = ""; + }); + run(() => { + update(form); + }); + run(() => { + token && token?.length === 6 && tick().then(() => btn.click()); + }); + let src; + run(() => { + src = `/api/public/${punks[index]}.webp`; + }); </script> {#if need2fa} @@ -163,17 +178,17 @@ type="file" class="hidden" bind:this={avatarInput} - on:change={(e) => handleFile(e, "profile")} + onchange={(e) => handleFile(e, "profile")} /> <div class="relative"> <button class="absolute w-8 h-12 left-12 bg-base-100 rounded top-12" - on:click={decr} + onclick={decr} > - <iconify-icon icon="ph:caret-left-bold" width="32" /> + <iconify-icon icon="ph:caret-left-bold" width="32"></iconify-icon> </button> - <div class="block relative w-32 mx-auto" on:click={selectAvatar}> + <div class="block relative w-32 mx-auto" onclick={selectAvatar}> <button class="w-32 h-32 rounded-full border-4 border-white overflow-hidden flex mx-auto relative" > @@ -186,14 +201,14 @@ <button class="absolute bg-base-100 rounded-full p-2 mx-auto right-0 bottom-0 z-10 w-12" > - <iconify-icon icon="ph:upload-simple-bold" width="24" /> + <iconify-icon icon="ph:upload-simple-bold" width="24"></iconify-icon> </button> </div> <button class="absolute w-8 h-12 right-12 bg-base-100 rounded top-12" - on:click={incr} + onclick={incr} > - <iconify-icon icon="ph:caret-right-bold" width="32" /> + <iconify-icon icon="ph:caret-right-bold" width="32"></iconify-icon> </button> </div> @@ -203,7 +218,7 @@ </div> {/if} - <form class="space-y-5" on:submit|preventDefault={handleSubmit} method="POST"> + <form class="space-y-5" onsubmit={preventDefault(handleSubmit)} method="POST"> <input type="hidden" name="loginRedirect" @@ -222,17 +237,17 @@ type="text" required bind:value={username} - on:focus={clear} + onfocus={clear} autocapitalize="none" placeholder={$t("login.username")} /> <iconify-icon class="cursor-pointer" tabindex="-1" - on:click={refresh} + onclick={refresh} icon="ph:dice-three-bold" width="32" - /> +></iconify-icon> </label> <label @@ -257,17 +272,17 @@ required bind:value={$password} autocapitalize="none" - on:focus={clear} + onfocus={clear} placeholder={$t("login.password")} /> {/if} <iconify-icon tabindex="-1" class="cursor-pointer" - on:click={() => (revealPassword = !revealPassword)} + onclick={() => (revealPassword = !revealPassword)} icon={revealPassword ? "ph:eye-bold" : "ph:eye-slash-bold"} width="32" - /> +></iconify-icon> </label> <button type="submit" class="btn" disabled={loading} bind:this={btn}> diff --git a/src/routes/(static)/support/+page.svelte b/src/routes/(static)/support/+page.svelte index 062f552b..b47c5c1a 100644 --- a/src/routes/(static)/support/+page.svelte +++ b/src/routes/(static)/support/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { browser } from "$app/environment"; import { onDestroy } from "svelte"; import { fail, success, post } from "$lib/utils"; @@ -6,16 +8,18 @@ import Icon from "$comp/Icon.svelte"; import { t } from "$lib/translations"; - export let data; + let { data = $bindable() } = $props(); let { user } = data; - $: if (user) { - data.subject = { ...user }; - } + run(() => { + if (user) { + data.subject = { ...user }; + } + }); - let email; - let message; - let sent; + let email = $state(); + let message = $state(); + let sent = $state(); let recaptchaSiteKey = "6LfCd8YkAAAAANmVJgzN3SQY3n3fv1RhiS5PgMYM"; let submit = (e) => { @@ -80,7 +84,7 @@ > and we'll do our best to get back to you in a timely manner. </p> - <form on:submit={submit}> + <form onsubmit={submit}> <div class="mb-4"> <label for="account" class="font-semibold" >{$t("user.support.accountName")}</label @@ -110,7 +114,7 @@ name="message" bind:value={message} required - /> +></textarea> </div> <button diff --git a/src/routes/+error.svelte b/src/routes/+error.svelte index faa7d738..c9e65806 100644 --- a/src/routes/+error.svelte +++ b/src/routes/+error.svelte @@ -2,7 +2,7 @@ import Icon from "$comp/Icon.svelte"; import { page } from "$app/stores"; - export let data; + let { data } = $props(); let { user } = data; let link = user ? `/${user.username}` : "/"; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index e5aeb206..a2dc3bff 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import { browser } from "$app/environment"; import { PUBLIC_DOMAIN } from "$env/static/public"; import "../app.css"; @@ -6,15 +8,17 @@ import { onMount } from "svelte"; import { installPrompt, theme as themeStore } from "$lib/store"; - export let data; - let { pathname, theme } = data; + let { data, children } = $props(); + let { pathname, theme } = $state(data); $themeStore = theme; let host = PUBLIC_DOMAIN.includes("localhost") ? `http://${PUBLIC_DOMAIN}` : `https://${PUBLIC_DOMAIN}`; - $: theme = $themeStore + run(() => { + theme = $themeStore + }); onMount(() => { if (!browser) return; @@ -48,7 +52,7 @@ {#if !$loading} <main data-theme={theme}> - <slot /> + {@render children?.()} </main> {/if} diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index a04d669e..480ea1c4 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,4 +1,6 @@ <script> + import { run } from 'svelte/legacy'; + import LandingHeader from "$comp/LandingHeader.svelte"; import LandingHero from "$comp/LandingHero.svelte"; import LandingInfoCard from "$comp/LandingInfoCard.svelte"; @@ -11,14 +13,16 @@ import { locale, t } from "$lib/translations"; import { onDestroy, onMount, tick } from "svelte"; - export let data; - let { faqs, locations, user } = data; + let { data } = $props(); + let { faqs, locations, user } = $state(data); let update = (data) => ({ faqs, locations, user } = data); - $: update(data); + run(() => { + update(data); + }); - let howItWorks; - let faq; - let about; + let howItWorks = $state(); + let faq = $state(); + let about = $state(); const howItWorksSteps = [ { image: "coinos:hand", stepID: "step1" }, @@ -26,7 +30,7 @@ { image: "coinos:smile", stepID: "step3" }, ]; - let loaded; + let loaded = $state(); let observer; @@ -66,8 +70,8 @@ title={$t("landing.info3.title")} description={$t("landing.info3.description")} /> - <div bind:this={howItWorks} /> - <div id="about" /> + <div bind:this={howItWorks}></div> + <div id="about"></div> </div> <div> @@ -79,7 +83,7 @@ <HowItWorksCard image={step.image} stepID={step.stepID} /> {/each} </div> - <div bind:this={faq} /> + <div bind:this={faq}></div> </div> <div> @@ -91,7 +95,7 @@ <FaqCard questionID={f} /> {/each} </div> - <div bind:this={about} /> + <div bind:this={about}></div> </div> <About /> diff --git a/src/routes/map/+page.svelte b/src/routes/map/+page.svelte index 2addca54..3e0fae5a 100644 --- a/src/routes/map/+page.svelte +++ b/src/routes/map/+page.svelte @@ -1,7 +1,7 @@ <script> import Icon from "$comp/Icon.svelte"; import LocationsMap from "$comp/LocationsMap.svelte"; - export let data; + let { data } = $props(); let { locations } = data; </script> |
