diff options
| author | Adam Soltys <[email protected]> | 2024-11-08 15:19:04 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2024-11-08 15:19:04 -0800 |
| commit | 84fb4b209a2650b2a93f3208ee9a23a44d8283c7 (patch) | |
| tree | 8687566bd8eac12de99439d448773d8ce5dc34b4 /src | |
| parent | 32fcc461cd43c8907df5e306d520bb671307eab1 (diff) | |
| download | coinos-ui-84fb4b209a2650b2a93f3208ee9a23a44d8283c7.tar.gz coinos-ui-84fb4b209a2650b2a93f3208ee9a23a44d8283c7.zip | |
svelte 5 fixups
Diffstat (limited to 'src')
22 files changed, 231 insertions, 277 deletions
diff --git a/src/components/Avatar.svelte b/src/components/Avatar.svelte index 3007c3e7..04f346b1 100644 --- a/src/components/Avatar.svelte +++ b/src/components/Avatar.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { run } from 'svelte/legacy'; + import { run } from "svelte/legacy"; import { avatar, banner } from "$lib/store"; import Icon from "$comp/Icon.svelte"; @@ -17,8 +17,12 @@ let link = $derived(user?.anon ? `/${user.pubkey}` : `/${user.username}`); let base = "/api/public"; - let profile = $derived(user?.profile ? `${base}/${user.profile}.webp` : user?.picture); - let fallback = $derived(`${base}/punks/` + punk(user.pubkey || user.id || "aa")); + let profile = $derived( + user?.profile ? `${base}/${user.profile}.webp` : user?.picture, + ); + let fallback = $derived( + `${base}/punks/` + punk(user.pubkey || user.id || "aa"), + ); let tmp = $derived($avatar?.id && $avatar.id === user.id && $avatar.src); let src; run(() => { @@ -28,7 +32,7 @@ let handle = () => (src = fallback); </script> -<a href={link} class:pointer-events-none={disabled}> +{#snippet body()} <div class="w-{s} h-{s} rounded-full border-4 border-base-100 overflow-hidden bg-gradient-to-r from-primary to-gradient flex justify-center items-center" > @@ -39,4 +43,12 @@ onerror={handle} /> </div> -</a> +{/snippet} + +{#if disabled} + {@render body()} +{:else} + <a href={link} class:pointer-events-none={disabled}> + {@render body()} + </a> +{/if} diff --git a/src/components/InvoiceData.svelte b/src/components/InvoiceData.svelte index da1ea5d9..2298d150 100644 --- a/src/components/InvoiceData.svelte +++ b/src/components/InvoiceData.svelte @@ -4,7 +4,6 @@ showQr, src, link, - qr = $bindable(), txt, invoice, amount, @@ -21,7 +20,6 @@ <img {src} class="mx-auto z-10 max-w-[360px] border-4 border-white" - bind:this={qr} alt={txt} /> </a> diff --git a/src/components/LocationsMap.svelte b/src/components/LocationsMap.svelte index b04b8e98..36223b75 100644 --- a/src/components/LocationsMap.svelte +++ b/src/components/LocationsMap.svelte @@ -1,7 +1,6 @@ <script> import { tick, onMount, onDestroy, mount } from "svelte"; import { browser } from "$app/environment"; - import Icon from "$comp/Icon.svelte"; import Popup from "$comp/Popup.svelte"; import { back } from "$lib/utils"; @@ -9,7 +8,8 @@ let { locations } = $props(); let map; - let mapContainer = $state(), mapWrapper = $state(); + let mapContainer = $state(), + mapWrapper = $state(); let markers = []; let search = $state(); let clearSearch = (e) => (search = ""); @@ -49,7 +49,6 @@ } }; - let scroll = () => { const el = document.querySelector(".selected"); if (el) @@ -197,9 +196,9 @@ let popupContainer = document.createElement("div"); mount(Popup, { - target: popupContainer, - props: { tags }, - }); + target: popupContainer, + props: { tags }, + }); let marker = new maplibre.Marker({ color: "#F7931A", scale: 0.65 }) .setLngLat([lon, lat]) @@ -247,11 +246,13 @@ }); onDestroy(() => map && map.remove()); - let list = $derived(search - ? markers.filter((m) => - m.tags.name.toLowerCase().includes(search.toLowerCase()), - ) - : inview); + let list = $derived( + search + ? markers.filter((m) => + m.tags.name.toLowerCase().includes(search.toLowerCase()), + ) + : inview, + ); </script> <div class="w-screen h-dvh flex" id="map" bind:this={mapWrapper}> @@ -259,29 +260,29 @@ id="map-container" class="mx-auto h-full w-full z-0" bind:this={mapContainer} -></div> + ></div> <div class="absolute flex top-2 left-2 gap-2"> <button - class="rounded-full border-2 border-black bg-base-100 w-10 h-10" + class="rounded-full border-2 border-black bg-base-100 w-16 h-16 flex items-center justify-center bg-opacity-80" onclick={back} > - <Icon icon="arrow-left" style="w-4 m-auto" /> + <iconify-icon icon="ph:arrow-left-bold" width="24"></iconify-icon> </button> </div> <div class="relative"> {#if !showList} <div - class="space-y-1 text-sm w-[300px] max-w-[calc(100vw*0.5)] h-[300px] max-h-[calc(100vh*0.4)] overflow-y-scroll p-4 bg-opacity-90 bg-white absolute right-4 bottom-8 rounded-2xl shadow text-ellipsis overflow-x-hidden" + class="space-y-1 text-sm w-[300px] max-w-[calc(100vw*0.5)] h-[300px] max-h-[calc(100vh*0.4)] overflow-y-scroll p-4 bg-opacity-90 bg-base-100 absolute right-4 bottom-8 rounded-2xl shadow text-ellipsis overflow-x-hidden" > - <div class="relative mb-4 sticky top-0 bg-white z-10"> + <div class="relative mb-4 sticky top-0 bg-base-100 z-10"> <input bind:value={search} class="w-full" /> <div class="flex gap-1 absolute right-6 top-3"> {#if search} <button onclick={clearSearch}> - <Icon icon="close" style="w-8" /> + <iconify-icon icon="ph:x-bold" width="32"></iconify-icon> </button> {:else} - <Icon icon="search" style="w-8" /> + <iconify-icon icon="ph:search-bold" width="32"></iconify-icon> {/if} </div> </div> @@ -300,19 +301,19 @@ {/if} <div class="absolute flex top-2 right-2 gap-2"> <button - class="rounded-full border-2 border-black bg-white w-10 h-10" + class="rounded-full border-2 border-primary bg-base-100 w-16 h-16 flex items-center justify-center bg-opacity-80" onclick={toggleList} > - <Icon icon="list" style="w-4 m-auto" /> + <iconify-icon icon="ph:list-bold" width="24"></iconify-icon> </button> <button - class="rounded-full border-2 border-black bg-white w-10 h-10" + class="rounded-full border-2 border-primary bg-base-100 w-16 h-16 flex items-center justify-center bg-opacity-80" onclick={toggle} > {#if timeout} - <Icon icon="pause" style="w-4 m-auto" /> + <iconify-icon icon="ph:pause-bold" width="24"></iconify-icon> {:else} - <Icon icon="play" style="w-4 m-auto" /> + <iconify-icon icon="ph:play-bold" width="24"></iconify-icon> {/if} </button> </div> diff --git a/src/components/Numpad.svelte b/src/components/Numpad.svelte index 03c7c48f..07d1ef4c 100644 --- a/src/components/Numpad.svelte +++ b/src/components/Numpad.svelte @@ -1,33 +1,21 @@ -<script lang="ts"> - import { run, preventDefault, stopPropagation } from "svelte/legacy"; - +<script> import Left from "$comp/Left.svelte"; import Icon from "$comp/Icon.svelte"; import { f, s, focus, warning, sat, sats } from "$lib/utils"; import { t } from "$lib/translations"; - interface Props { - amount: any; - currency: any; - element: any; - fiat?: any; - rate: any; - submit?: any; - amountFiat?: number; - } - - let { - amount = $bindable(), + export let amount, currency, - element = $bindable(), - fiat = $bindable(!amount), - rate = $bindable(), - submit = undefined, - amountFiat = $bindable(0), - }: Props = $props(); + element, + fiat = !amount, + rate, + submit = undefined; + + export let amountFiat = 0; let arrow = "<"; + $: update(amount, amountFiat); let update = (a, f) => { if (fiat) { amount = Math.round(f / (rate / sats)); @@ -114,6 +102,8 @@ } }; + $: html = fiat ? amountFiat : s(amount); + let prev = ""; let input = (e) => { @@ -203,13 +193,6 @@ } fiat = !fiat; }; - run(() => { - update(amount, amountFiat); - }); - let html; - run(() => { - html = fiat ? amountFiat : s(amount); - }); </script> <div class="flex justify-center items-center"> @@ -225,17 +208,17 @@ use:focus contenteditable bind:innerHTML={html} - onfocus={select} - onblur={blur} - oninput={input} - onkeydown={keydown} + on:focus={select} + on:blur={blur} + on:input={input} + on:keydown={keydown} class="outline-none my-auto" bind:this={element} - ></div> + /> </div> <div class="flex items-center justify-center text-2xl cursor-pointer" - onclick={stopPropagation(preventDefault(swap))} + on:click|preventDefault|stopPropagation={swap} > {fiat ? "⚡️" + s(amount) : f(amountFiat, currency)} </div> @@ -247,7 +230,7 @@ <button type="button" class="btn" - onclick={stopPropagation(preventDefault(() => handleInput(value)))} + on:click|preventDefault|stopPropagation={() => handleInput(value)} > <Left /> </button> @@ -255,7 +238,7 @@ <button type="button" class="btn" - onclick={stopPropagation(preventDefault(() => handleInput(value)))} + on:click|preventDefault|stopPropagation={() => handleInput(value)} >{value}</button > {/if} diff --git a/src/components/Pin.svelte b/src/components/Pin.svelte index da53577e..fb17c612 100644 --- a/src/components/Pin.svelte +++ b/src/components/Pin.svelte @@ -1,36 +1,28 @@ -<script lang="ts"> - import { run, createBubbler, preventDefault } from "svelte/legacy"; - - const bubble = createBubbler(); +<script> import { t } from "$lib/translations"; import { post, success, fail, focus, setCookie } from "$lib/utils"; import Pinpad from "$comp/Pinpad.svelte"; import { pin } from "$lib/store"; import { onMount } from "svelte"; - interface Props { - value?: string; - title?: any; - cancel?: any; - notify?: boolean; - } - - let { - value = $bindable(""), - title = $t("user.settings.verifyPIN"), - cancel = () => (p = ""), - notify = true, - }: Props = $props(); + export let value = ""; + export let title = $t("user.settings.verifyPIN"); + export let cancel = () => (p = ""); + export let notify = true; - let p = $state(""); + let p = ""; + $: update(value); let update = (value) => (p = value); - let loaded = $state(); + $: p.toString().length > 5 && (value = p.toString()); + + let loaded; onMount(() => setTimeout(() => (loaded = true), 500)); - let locktime = $state(30 * 60); + let locktime = 30 * 60; + $: loaded && checkPin(p); let checkPin = async (p) => { if (p?.length !== 6) return; let result; @@ -49,21 +41,12 @@ value = ""; } }; - run(() => { - p.toString().length > 5 && (value = p.toString()); - }); - run(() => { - update(value); - }); - run(() => { - loaded && checkPin(p); - }); </script> {#if loaded} <div class="fixed bg-base-100 bg-opacity-90 inset-0 h-full w-full z-50 cursor-default" - onclick={preventDefault(bubble("click"))} + on:click|preventDefault > <div class="mx-auto p-5 border shadow-lg rounded-md bg-base-100 space-y-5 max-w-lg" @@ -75,7 +58,10 @@ <label for="locktime" class="font-bold" >{$t("user.settings.rememberFor")}</label > - <select name="locktime" bind:value={locktime}> + <select + name="locktime" + bind:value={locktime} + > <option value={30}>30 {$t("user.settings.seconds")}</option> <option value={5 * 60}>5 {$t("user.settings.minutes")}</option> <option value={10 * 60}>10 {$t("user.settings.minutes")}</option> @@ -86,7 +72,7 @@ </div> <div class="w-full flex"> - <button class="btn" onclick={preventDefault(cancel)}> + <button class="btn" on:click|preventDefault={cancel}> <div class="my-auto">Cancel</div> </button> </div> diff --git a/src/lib/settings.ts b/src/lib/settings.ts new file mode 100644 index 00000000..b78d83fe --- /dev/null +++ b/src/lib/settings.ts @@ -0,0 +1,31 @@ +import { auth, fd, get, post } from "$lib/utils"; +import { fail } from "@sveltejs/kit"; + +type Error = { + message: string; +}; + +export default async ({ cookies, request }) => { + const form = await fd(request); + + if (form.tab === "pos") { + form.notify = form.notify === "on"; + form.push = form.push === "on"; + form.nip5 = form.nip5 === "on"; + form.prompt = form.prompt === "on"; + form.autowithdraw = form.autowithdraw === "on"; + } + + let user = { ...(await get("/me", auth(cookies))), ...form }; + + try { + ({ user } = await post("/user", user, auth(cookies))); + } catch (e) { + const { message } = e as Error; + return fail(400, { message }); + } + + if (user.language) cookies.set("lang", user.language, { path: "/" }); + + return { user, success: true }; +}; diff --git a/src/lib/store.ts b/src/lib/store.ts index 5c7a0957..e294329e 100644 --- a/src/lib/store.ts +++ b/src/lib/store.ts @@ -61,3 +61,4 @@ export const theme = writable("light"); export const token = persistSession("token"); export const ndef = writable(); export const showQr = persistLocal("showQr", true); +export const save = writable(); diff --git a/src/routes/(app)/invoice/[id]/+layout.server.ts b/src/routes/(app)/invoice/[id]/+layout.server.ts index e428d9fe..9b667c7b 100644 --- a/src/routes/(app)/invoice/[id]/+layout.server.ts +++ b/src/routes/(app)/invoice/[id]/+layout.server.ts @@ -35,6 +35,7 @@ export async function load({ cookies, depends, params, url, parent }) { } } + console.log("REDRAW", invoice?.text); const src = Qr.drawImg(invoice?.text || "", { size: 500 }); const theme = cookies.get("theme"); return { id, invoice, subject, src, user, token, theme }; diff --git a/src/routes/(app)/invoice/[id]/+page.svelte b/src/routes/(app)/invoice/[id]/+page.svelte index fef43e4d..ded42016 100644 --- a/src/routes/(app)/invoice/[id]/+page.svelte +++ b/src/routes/(app)/invoice/[id]/+page.svelte @@ -26,7 +26,8 @@ let readingerror = (e) => console.log("nfc error", e); - let { invoice, id, subject, user, src } = $state(data); + let { invoice, id, subject, user } = $state(data); + let src = $derived(data.src); let { aid, amount, @@ -38,32 +39,15 @@ user: { username, currency }, } = $state(invoice); - let qr = $state(); - let tipPercent = 0; + let tipPercent = $derived(tip ? (tip / amount) * 100 : 0); - let refresh = async (data) => { - ({ invoice, id, user, src } = data); - ({ - aid, - amount, - hash, - type, - rate, - text, - tip, - user: { username, currency }, - } = invoice); - - if (browser && !subbed[id]) - send("subscribe", invoice) - .then(() => (subbed[id] = true)) - .catch((e) => { - console.log("failed to subscribe to invoice notifications", invoice); - console.log(e); - }); - - tipPercent = (tip / amount) * 100; - }; + // if (browser && !subbed[id]) + // send("subscribe", invoice) + // .then(() => (subbed[id] = true)) + // .catch((e) => { + // console.log("failed to subscribe to invoice notifications", invoice); + // console.log(e); + // }); let subbed = {}; @@ -90,6 +74,7 @@ }; let setAmount = $state(async () => { + console.log("LALA", newAmount); if (typeof $amountPrompt === "undefined") $amountPrompt = true; settingAmount = false; amount = newAmount; @@ -104,6 +89,7 @@ if (subject?.prompt) url += "/tip"; else url += "?options=true"; + console.log("GO", url); goto(url, { invalidateAll: true, noScroll: true }); }); @@ -112,31 +98,20 @@ 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 amountFiat = $derived(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; - }); + 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"> <InvoiceData {src} {link} - {qr} {txt} {invoice} {amount} diff --git a/src/routes/(app)/send/[...text]/+page.svelte b/src/routes/(app)/send/[...text]/+page.svelte index 7ec76bc9..6b93b94b 100644 --- a/src/routes/(app)/send/[...text]/+page.svelte +++ b/src/routes/(app)/send/[...text]/+page.svelte @@ -1,5 +1,5 @@ <script> - import { run } from 'svelte/legacy'; + import { run } from "svelte/legacy"; import { page } from "$app/stores"; import { fly } from "svelte/transition"; @@ -17,7 +17,10 @@ let { contacts } = data; - let el = $state(), text = $state(), pasted = $state(), w = $state(); + let el = $state(), + text = $state(), + pasted = $state(), + w = $state(); let keypress = (e) => e.key === "Enter" ? e.preventDefault() || el.click() : (pasted = false); @@ -60,7 +63,7 @@ bind:value={text} onpaste={() => (pasted = true)} autocapitalize="none" -></textarea> + ></textarea> <div class="flex gap-2"> <a href="/scan" class="contents"> @@ -95,18 +98,12 @@ {$t("user.send.contacts")} </h1> <div> - {#each contacts as c} - <a href={`/pay/${c.username}`}> - <div class="border-b p-2 last:border-b-0 hover:bg-base-200"> - <div class="flex"> - <div> - <div class="flex"> - <Avatar user={c} size={20} disabled={true} /> - <div class="my-auto text-left"> - <p class="ml-1 text-lg break-words">{c.username}</p> - </div> - </div> - </div> + {#each contacts as c, i} + <a href={`/pay/${c.username}`} class="contents"> + <div class="flex hover:bg-base-200 p-2"> + <Avatar user={c} size={20} disabled={true} /> + <div class="my-auto text-left"> + <p class="ml-1 text-lg break-words">{c.username}</p> </div> </div> </a> diff --git a/src/routes/(app)/settings/+layout.server.ts b/src/routes/(app)/settings/+layout.server.ts new file mode 100644 index 00000000..cd63d4f0 --- /dev/null +++ b/src/routes/(app)/settings/+layout.server.ts @@ -0,0 +1,10 @@ +import { auth, get } from "$lib/utils"; +import { redirect } from "@sveltejs/kit"; + +export async function load({ cookies, params, url }) { + const tab = url.pathname.split("/").filter(Boolean).pop(); + if (tab === "settings") redirect(307, `${url.pathname}/account`); + params.cookies = cookies.getAll(); + const subscriptions = await get("/subscriptions", auth(cookies)); + return { cookies: cookies.getAll(), subscriptions, tab }; +} diff --git a/src/routes/(app)/settings/[...tab]/+page.svelte b/src/routes/(app)/settings/+layout.svelte index 5b9e048d..edf256ab 100644 --- a/src/routes/(app)/settings/[...tab]/+page.svelte +++ b/src/routes/(app)/settings/+layout.svelte @@ -1,5 +1,6 @@ <script> - import { run, preventDefault } from 'svelte/legacy'; + import { run, preventDefault } from "svelte/legacy"; + import { setContext } from "svelte"; import { browser } from "$app/environment"; import { onMount, tick } from "svelte"; @@ -11,33 +12,20 @@ import Pin from "$comp/Pin.svelte"; import { loading, t } from "$lib/translations"; import { fail, auth, post, sleep, warning, success } from "$lib/utils"; - import { avatar, banner, password, pin } from "$lib/store"; + import { avatar, banner, password, pin, save } from "$lib/store"; import { upload } from "$lib/upload"; import { page } from "$app/stores"; import { sign, send, reEncryptEntropy, setNsec } from "$lib/nostr"; import { invalidateAll } from "$app/navigation"; - - import Account from "./_account.svelte"; - import Pos from "./_pos.svelte"; - import Security from "./_security.svelte"; - import Shopify from "./_shopify.svelte"; - import { PUBLIC_COINOS_URL } from "$env/static/public"; let { data, form } = $props(); - let submit = $state(); let formElement = $state(); - let { user, token, rates, tab, cookies, subscriptions } = $state(data); - let prev; - - let update = () => { - ({ user, token, rates, tab, subscriptions } = data); - prev = { ...user }; - }; - - + let { user, token, rates, cookies, subscriptions } = $state(data); + let { tab } = $derived(data); + let prev = $derived({ ...user }); let justUpdated; let throttledSuccess = () => { @@ -48,20 +36,16 @@ } }; - - let tabs = [ - { name: "account", key: "ACCOUNT", comp: Account }, - { name: "pos", key: "POINT_OF_SALE", comp: Pos }, - { name: "security", key: "SECURITY", comp: Security }, - { name: "shopify", key: "SHOPIFY", comp: Shopify }, + { name: "account", key: "ACCOUNT" }, + { name: "preferences", key: "POINT_OF_SALE" }, + { name: "security", key: "SECURITY" }, + { name: "shopify", key: "SHOPIFY" }, ]; - let { address, id, username } = user; let submitting = $state(); - async function handleSubmit() { try { submitting = true; @@ -182,9 +166,6 @@ submitting = false; } run(() => { - update(data); - }); - run(() => { form?.user && ({ user } = form); }); run(() => { @@ -199,13 +180,10 @@ $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} @@ -227,9 +205,7 @@ {$t("user.settings.header")} </h1> - <div - class="flex justify-around items-center border-b pb-3" - > + <div class="flex justify-around items-center border-b pb-3"> {#each tabs.filter((t) => t.name !== "shopify") as { name, key }} <a href={`/settings/${name}`}> <button @@ -244,14 +220,14 @@ </div> </div> - <SvelteComponent {user} {rates} {submit} {subscriptions} /> + <slot /> </div> <div class="z-10 fixed bottom-0 bg-base-100 shadow border-t border-t-8 border-accent w-full flex justify-center items-center py-3" > <button - bind:this={submit} + bind:this={$save} type="submit" class="btn !w-auto" class:bg-base-200={submitting} diff --git a/src/routes/(app)/settings/+page.svelte b/src/routes/(app)/settings/+page.svelte new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/routes/(app)/settings/+page.svelte diff --git a/src/routes/(app)/settings/[...tab]/+page.server.ts b/src/routes/(app)/settings/[...tab]/+page.server.ts deleted file mode 100644 index 39533426..00000000 --- a/src/routes/(app)/settings/[...tab]/+page.server.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { auth, fd, get, post } from "$lib/utils"; -import { fail, redirect } from "@sveltejs/kit"; - -export async function load({ cookies, params, url }) { - if (url.pathname.endsWith("settings")) - redirect(307, `${url.pathname}/account`); - params.cookies = cookies.getAll(); - const subscriptions = await get("/subscriptions", auth(cookies)); - return { cookies: cookies.getAll(), subscriptions, tab: params.tab }; -} - -export const actions = { - default: async ({ cookies, request }) => { - const form = await fd(request); - - if (form.tab === "pos") { - form.notify = form.notify === "on"; - form.push = form.push === "on"; - form.nip5 = form.nip5 === "on"; - form.prompt = form.prompt === "on"; - form.autowithdraw = form.autowithdraw === "on"; - } - - let user = { ...(await get("/me", auth(cookies))), ...form }; - - try { - ({ user } = await post("/user", user, auth(cookies))); - } catch (e: any) { - return fail(400, { message: e.message }); - } - - if (user.language) cookies.set("lang", user.language, { path: "/" }); - - return { user, success: true }; - }, -}; diff --git a/src/routes/(app)/settings/account/+page.server.ts b/src/routes/(app)/settings/account/+page.server.ts new file mode 100644 index 00000000..4145935e --- /dev/null +++ b/src/routes/(app)/settings/account/+page.server.ts @@ -0,0 +1,5 @@ +import updateUser from "$lib/settings"; + +export const actions = { + default: updateUser, +}; diff --git a/src/routes/(app)/settings/[...tab]/_account.svelte b/src/routes/(app)/settings/account/+page.svelte index 54249265..77860948 100644 --- a/src/routes/(app)/settings/[...tab]/_account.svelte +++ b/src/routes/(app)/settings/account/+page.svelte @@ -4,11 +4,14 @@ import { t } from "$lib/translations"; import { page } from "$app/stores"; - let { user = $bindable(), rates, submit } = $props(); - + let { data } = $props(); + let { user, rates } = $state(data); let { id } = user; - let avatarFile, avatarInput = $state(), bannerFile, bannerInput = $state(); + let avatarFile, + avatarInput = $state(), + bannerFile, + bannerInput = $state(); let selectAvatar = () => avatarInput.click(); let selectBanner = () => bannerInput.click(); @@ -45,8 +48,6 @@ reader.readAsDataURL(file); }; - if (!user.display) user.display = user.username; - let url = $derived(`${$page.url.host}/${user.username}`); let full = $derived(`${$page.url.protocol}//${url}`); let addr = $derived(`${user.username}@${$page.url.host}`); @@ -79,17 +80,11 @@ > <input type="text" name="email" class="clean" bind:value={user.email} /> {#if user.verified} - <iconify-icon - icon="ph:check-bold" - class="text-success ml-auto" - width="32" -></iconify-icon> + <iconify-icon 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> + <iconify-icon icon="ph:clock-bold" class="text-warning ml-auto" width="32" + ></iconify-icon> {/if} </label> </div> @@ -116,7 +111,7 @@ onclick={selectAvatar} onkeydown={selectAvatar} > - <Icon icon="logo-symbol-white" style="mx-auto" /> + <iconify-icon icon="coinos:symbol" class="mx-auto"></iconify-icon> <iconify-icon icon="ph:floppy-disk-bold" width="32"></iconify-icon> </div> {/if} @@ -161,7 +156,7 @@ onclick={selectBanner} onkeydown={selectBanner} alt="Banner" -></div> + ></div> {/if} <button @@ -191,5 +186,5 @@ name="address" bind:value={user.address} placeholder={$t("user.settings.aboutPlaceholder")} -></textarea> + ></textarea> </div> diff --git a/src/routes/(app)/settings/preferences/+page.server.ts b/src/routes/(app)/settings/preferences/+page.server.ts new file mode 100644 index 00000000..4145935e --- /dev/null +++ b/src/routes/(app)/settings/preferences/+page.server.ts @@ -0,0 +1,5 @@ +import updateUser from "$lib/settings"; + +export const actions = { + default: updateUser, +}; diff --git a/src/routes/(app)/settings/[...tab]/_pos.svelte b/src/routes/(app)/settings/preferences/+page.svelte index 3f68eebc..762d25f5 100644 --- a/src/routes/(app)/settings/[...tab]/_pos.svelte +++ b/src/routes/(app)/settings/preferences/+page.svelte @@ -1,5 +1,5 @@ <script> - import { run } from 'svelte/legacy'; + import { run } from "svelte/legacy"; import { onMount, tick } from "svelte"; import { browser } from "$app/environment"; @@ -11,20 +11,19 @@ import { page } from "$app/stores"; import { PUBLIC_VAPID_PUBKEY } from "$env/static/public"; - let { - user = $bindable(), - rates, - submit, - subscriptions - } = $props(); - + let { data } = $props(); + let user = $derived(data.user); + let rates = $derived(data.rates); let { currency } = $state(user); let rate = $state(rates[currency]); let fiats = Object.keys(rates).sort((a, b) => a.localeCompare(b)); let keypress = (e) => e.key === "Enter" && (e.preventDefault() || el.click()); - let editingReserve = $state(), editingThreshold = $state(), doneReserve = $state(), doneThreshold; + let editingReserve = $state(), + editingThreshold = $state(), + doneReserve = $state(), + doneThreshold; let doneEditing = () => { editingReserve = false; editingThreshold = false; @@ -44,9 +43,12 @@ if (!user.threshold) user.threshold = 1000000; if (!user.reserve) user.reserve = 100000; - let reserveEl = $state(), thresholdEl = $state(); + let reserveEl = $state(), + thresholdEl = $state(); - let push = $state(), pm, subscription; + let push = $state(), + pm, + subscription; onMount(async () => { if (!browser) return; @@ -104,7 +106,7 @@ <label for="currency" class="font-bold block mb-1" >{$t("user.settings.localCurrency")}</label > - <select name="currency" value={user.currency}> + <select name="currency" value={currency}> {#each fiats as fiat} <option value={fiat}>{fiat}</option> {/each} @@ -168,7 +170,7 @@ onkeypress={keypress} class="w-full p-4 border rounded-xl h-48" bind:value={user.destination} -></textarea> + ></textarea> </div> <div> @@ -222,7 +224,7 @@ </h1> <Numpad bind:amount={user.threshold} - bind:currency + {currency} bind:rate bind:submit={doneReserve} bind:element={thresholdEl} diff --git a/src/routes/(app)/settings/security/+page.server.ts b/src/routes/(app)/settings/security/+page.server.ts new file mode 100644 index 00000000..4145935e --- /dev/null +++ b/src/routes/(app)/settings/security/+page.server.ts @@ -0,0 +1,5 @@ +import updateUser from "$lib/settings"; + +export const actions = { + default: updateUser, +}; diff --git a/src/routes/(app)/settings/[...tab]/_security.svelte b/src/routes/(app)/settings/security/+page.svelte index 8bb8a3fa..d3f27ee6 100644 --- a/src/routes/(app)/settings/[...tab]/_security.svelte +++ b/src/routes/(app)/settings/security/+page.svelte @@ -1,5 +1,6 @@ <script> - import { run } from 'svelte/legacy'; + import { run } from "svelte/legacy"; + import { getContext } from "svelte"; import { getMnemonic, getNsec } from "$lib/nostr"; import { tick } from "svelte"; @@ -8,11 +9,13 @@ import Icon from "$comp/Icon.svelte"; import Qr from "$comp/Qr.svelte"; import { copy, post, success, fail } from "$lib/utils"; - import { pin as current } from "$lib/store"; + import { save, pin as current } from "$lib/store"; import { invalidate } from "$app/navigation"; import { page } from "$app/stores"; - let { user = $bindable(), rates, submit } = $props(); + let { data } = $props(); + let { user, rates } = $state(data); + let { id } = user; let confirming2fa = $state(), disabling2fa = $state(), @@ -24,14 +27,14 @@ old, otp = $state(), password = $state(), - pin = $state(), + pin = $state(""), revealPassword = $state(), revealSeed, revealNsec = $state(), token = $state(""), setting2fa = $state(), settingPin = $state(), - verify = $state(); + verify = $state(""); let toggleImporting = () => { revealNsec = false; @@ -67,7 +70,7 @@ $current = pin; pin = ""; verify = ""; - submit.click(); + $save.click(); settingPin = false; verifying = false; } else { @@ -95,7 +98,7 @@ try { disablingPin = true; await tick(); - submit.click(); + $save.click(); } catch (e) { console.log(e); fail("Failed to disable pin"); @@ -138,6 +141,7 @@ cancel(); } } catch (e) { + console.log(e); fail("Failed to enable 2FA, try again"); } }; @@ -155,10 +159,7 @@ fail("Failed to disable 2FA, try again"); } }; - let verifying; - run(() => { - verifying = pin?.length > 5; - }); + let verifying = $derived(pin?.length > 5); run(() => { verify && checkPin(pin); }); @@ -170,6 +171,7 @@ }); </script> +{console.log("SAVE", $save)} <input type="hidden" name="newpin" value={disablingPin ? "delete" : pin} /> <input type="hidden" name="confirm" bind:value={password} /> @@ -191,7 +193,7 @@ <iconify-icon icon={revealPassword ? "ph:eye-bold" : "ph:eye-slash-bold"} width="32" -></iconify-icon> + ></iconify-icon> </button> </div> @@ -214,12 +216,11 @@ notify={false} /> {:else} - <button type="button" class="btn" onclick={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> + ></iconify-icon> {user.haspin ? $t("user.settings.disablePIN") : $t("user.settings.enablePIN")}</button diff --git a/src/routes/(app)/settings/[...tab]/_shopify.svelte b/src/routes/(app)/settings/shopify/+page.svelte index cc746c49..cc746c49 100644 --- a/src/routes/(app)/settings/[...tab]/_shopify.svelte +++ b/src/routes/(app)/settings/shopify/+page.svelte diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index ee0ed70c..0de57279 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -47,3 +47,9 @@ addIcon("coinos:smile", { width: 112, height: 108, }); + +addIcon("coinos:symbol", { + body: `<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M36 72C55.8823 72 72 55.8823 72 36C72 16.1177 55.8823 0 36 0C16.1177 0 0 16.1177 0 36C0 55.8823 16.1177 72 36 72ZM36 67.2C53.2313 67.2 67.2 53.2313 67.2 36C67.2 18.7687 53.2313 4.8 36 4.8C18.7687 4.8 4.8 18.7687 4.8 36C4.8 53.2313 18.7687 67.2 36 67.2Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M36.001 12.7998C36.0009 12.7998 36.0008 12.7998 36.0008 12.7998C23.1878 12.7998 12.8008 23.1868 12.8008 35.9998C12.8008 48.8128 23.1878 59.1998 36.0008 59.1998C36.0008 59.1998 36.0009 59.1998 36.001 59.1998V12.7998Z" fill="white"/></svg>`, + width: 72, + height: 72, +}); |
