aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-03-02 23:37:57 -0800
committerAdam Soltys <[email protected]>2026-03-02 23:37:57 -0800
commit68684395a080a834d823b39e2e9641372bbafbfd (patch)
treed9a02ed31ef3be0fe7c274b08597271e7dac8f15
parent97fffca3e63e2edb4818305abdbcbb8953344aa3 (diff)
downloadcoinos-ui-68684395a080a834d823b39e2e9641372bbafbfd.tar.gz
coinos-ui-68684395a080a834d823b39e2e9641372bbafbfd.zip
dependency audit
-rw-r--r--package-lock.json115
-rw-r--r--package.json8
-rw-r--r--src/components/Menu.svelte82
-rw-r--r--src/components/Payments.svelte12
-rw-r--r--src/components/Qr.svelte13
-rw-r--r--src/lib/locales.ts41
-rw-r--r--src/lib/random.ts28
-rw-r--r--src/lib/socket.ts5
-rw-r--r--src/lib/utils.ts34
-rw-r--r--src/routes/(app)/[username]/(profile)/+page.ts4
-rw-r--r--src/routes/(app)/[username]/accepted/[text]/raw/+server.ts10
-rw-r--r--src/routes/(app)/fund/[id]/+page.svelte1
-rw-r--r--src/routes/(app)/payment/[id]/+page.svelte7
-rw-r--r--src/routes/(app)/payment/[id]/plain/+page.svelte5
-rw-r--r--src/routes/(app)/payments/[...page]/+page.svelte14
-rw-r--r--src/routes/(app)/qr/[text]/raw/+server.ts10
-rw-r--r--src/routes/+layout.ts10
17 files changed, 105 insertions, 294 deletions
diff --git a/package-lock.json b/package-lock.json
index b745ce26..f65a409a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -33,38 +33,30 @@
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@types/uuid": "^11.0.0",
"@zerodevx/svelte-toast": "^0.9.6",
- "barcode-detector": "^3.0.8",
"bech32": "^2.0.0",
"bip21": "^3.0.0",
"bitcoin-address-validation": "^3.0.0",
"buffer": "^6.0.3",
"daisyui": "^5.5.17",
- "date-fns": "^4.1.0",
"esptool-js": "^0.5.7",
"husky": "^9.1.7",
- "js-cookie": "^3.0.5",
"lint-staged": "^16.2.7",
"nostr-tools": "^2.23.0",
"oxfmt": "^0.35.0",
"oxlint": "^1.35.0",
"playwright": "^1.58.2",
"qr-scanner": "^1.4.2",
- "qrcode-base64": "^1.0.1",
"rollup": "^4.57.1",
"rollup-plugin-visualizer": "^6.0.5",
- "screenfull": "^6.0.2",
"svelte": "^5.49.1",
"svelte-adapter-bun": "^1.0.1",
"svelte-confetti": "^2.3.2",
- "svelte-dnd-action": "^0.9.69",
- "svelte-outclick": "^4.2.0",
"svelte-preprocess": "^6.0.3",
"sveltekit-i18n": "^2.4.2",
"tailwind-scrollbar": "^4.0.2",
"tailwindcss": "^4.1.18",
"typescript": "^5.9.3",
"uint8array-extras": "^1.5.0",
- "unique-names-generator": "^4.7.1",
"unplugin-icons": "^23.0.1",
"uuid": "^13.0.0",
"vite": "^7.3.1",
@@ -2451,11 +2443,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/emscripten": {
- "version": "1.41.5",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/estree": {
"version": "1.0.8",
"license": "MIT"
@@ -2698,14 +2685,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/barcode-detector": {
- "version": "3.0.8",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "zxing-wasm": "2.2.4"
- }
- },
"node_modules/bare-events": {
"version": "2.6.1",
"dev": true,
@@ -3596,15 +3575,6 @@
"node": ">=8"
}
},
- "node_modules/date-fns": {
- "version": "4.1.0",
- "dev": true,
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/kossnocorp"
- }
- },
"node_modules/dateformat": {
"version": "3.0.3",
"dev": true,
@@ -4884,14 +4854,6 @@
"jiti": "lib/jiti-cli.mjs"
}
},
- "node_modules/js-cookie": {
- "version": "3.0.5",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/js-tokens": {
"version": "4.0.0",
"dev": true,
@@ -6547,11 +6509,6 @@
"node": ">=10.13.0"
}
},
- "node_modules/qrcode-base64": {
- "version": "1.0.1",
- "dev": true,
- "license": "MIT"
- },
"node_modules/qrcode/node_modules/yargs": {
"version": "15.4.1",
"license": "MIT",
@@ -7162,17 +7119,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/screenfull": {
- "version": "6.0.2",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/semver": {
"version": "7.7.2",
"license": "ISC",
@@ -7643,22 +7589,6 @@
"svelte": ">=5.0.0"
}
},
- "node_modules/svelte-dnd-action": {
- "version": "0.9.69",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "svelte": ">=3.23.0 || ^5.0.0-next.0"
- }
- },
- "node_modules/svelte-outclick": {
- "version": "4.2.0",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "svelte": ">= 5"
- }
- },
"node_modules/svelte-preprocess": {
"version": "6.0.3",
"dev": true,
@@ -7728,17 +7658,6 @@
"svelte": ">=3.49.0"
}
},
- "node_modules/tagged-tag": {
- "version": "1.0.0",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/tailwind-scrollbar": {
"version": "4.0.2",
"dev": true,
@@ -8035,20 +7954,6 @@
"node": "*"
}
},
- "node_modules/type-fest": {
- "version": "5.4.3",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "dependencies": {
- "tagged-tag": "^1.0.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/typescript": {
"version": "5.9.3",
"dev": true,
@@ -8096,14 +8001,6 @@
"devOptional": true,
"license": "MIT"
},
- "node_modules/unique-names-generator": {
- "version": "4.7.1",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/unique-string": {
"version": "2.0.0",
"dev": true,
@@ -8556,18 +8453,6 @@
"version": "1.1.4",
"dev": true,
"license": "MIT"
- },
- "node_modules/zxing-wasm": {
- "version": "2.2.4",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/emscripten": "^1.41.5",
- "type-fest": "^5.2.0"
- },
- "peerDependencies": {
- "@types/emscripten": ">=1.39.6"
- }
}
}
}
diff --git a/package.json b/package.json
index 8fb3476c..62801cc9 100644
--- a/package.json
+++ b/package.json
@@ -45,38 +45,30 @@
"@sveltejs/vite-plugin-svelte": "^6.2.4",
"@types/uuid": "^11.0.0",
"@zerodevx/svelte-toast": "^0.9.6",
- "barcode-detector": "^3.0.8",
"bech32": "^2.0.0",
"bip21": "^3.0.0",
"bitcoin-address-validation": "^3.0.0",
"buffer": "^6.0.3",
"daisyui": "^5.5.17",
- "date-fns": "^4.1.0",
"esptool-js": "^0.5.7",
"husky": "^9.1.7",
- "js-cookie": "^3.0.5",
"lint-staged": "^16.2.7",
"nostr-tools": "^2.23.0",
"oxfmt": "^0.35.0",
"oxlint": "^1.35.0",
"playwright": "^1.58.2",
"qr-scanner": "^1.4.2",
- "qrcode-base64": "^1.0.1",
"rollup": "^4.57.1",
"rollup-plugin-visualizer": "^6.0.5",
- "screenfull": "^6.0.2",
"svelte": "^5.49.1",
"svelte-adapter-bun": "^1.0.1",
"svelte-confetti": "^2.3.2",
- "svelte-dnd-action": "^0.9.69",
- "svelte-outclick": "^4.2.0",
"svelte-preprocess": "^6.0.3",
"sveltekit-i18n": "^2.4.2",
"tailwind-scrollbar": "^4.0.2",
"tailwindcss": "^4.1.18",
"typescript": "^5.9.3",
"uint8array-extras": "^1.5.0",
- "unique-names-generator": "^4.7.1",
"unplugin-icons": "^23.0.1",
"uuid": "^13.0.0",
"vite": "^7.3.1",
diff --git a/src/components/Menu.svelte b/src/components/Menu.svelte
index 94fc7c3a..ca64a289 100644
--- a/src/components/Menu.svelte
+++ b/src/components/Menu.svelte
@@ -9,7 +9,6 @@
import CoinosLogo from "virtual:icons/coinos/logo";
import { theme } from "$lib/store";
import DarkToggle from "$comp/DarkToggle.svelte";
- import { OutClick } from "svelte-outclick";
let { t, user, w, opacity } = $props();
let dark = () => ($theme = $theme === "dark" ? "light" : "dark");
@@ -26,47 +25,50 @@
let hideMenu = () => (showMenu = false);
let toggleMenu = () => (showMenu = !showMenu);
+
+ const clickOutside = (node, callback) => {
+ const handler = (e) => { if (!node.contains(e.target)) callback(); };
+ document.addEventListener("click", handler, true);
+ return { destroy: () => document.removeEventListener("click", handler, true) };
+ };
</script>
-<div>
- <OutClick onOutClick={hideMenu}>
- <button class="flex justify-center items-center bg-base-100 p-2 rounded-full w-12 h-12 sm:w-16 sm:h-16 drop-shadow-xl {opacity('/support')}" onclick={toggleMenu} aria-label="Open menu">
- <PhListBold width={w > 640 ? 32 : 24} />
- </button>
+<div use:clickOutside={hideMenu}>
+ <button class="flex justify-center items-center bg-base-100 p-2 rounded-full w-12 h-12 sm:w-16 sm:h-16 drop-shadow-xl {opacity('/support')}" onclick={toggleMenu} aria-label="Open menu">
+ <PhListBold width={w > 640 ? 32 : 24} />
+ </button>
- <div
- class="absolute top-14 right-0 bg-base-100 rounded-3xl p-8 shadow-xl z-50"
- class:hidden={!showMenu}
- class:block={showMenu}
- >
- <ul class="space-y-5 w-48">
- {#each menuButtons as { href, icon: Icon, key }}
- <li>
- {#if key.includes("dark")}
- <DarkToggle />
- {:else}
- <a
- {href}
- data-sveltekit-preload-code="eager"
- data-sveltekit-preload-data="false"
- onclick={hideMenu}
+ <div
+ class="absolute top-14 right-0 bg-base-100 rounded-3xl p-8 shadow-xl z-50"
+ class:hidden={!showMenu}
+ class:block={showMenu}
+ >
+ <ul class="space-y-5 w-48">
+ {#each menuButtons as { href, icon: Icon, key }}
+ <li>
+ {#if key.includes("dark")}
+ <DarkToggle />
+ {:else}
+ <a
+ {href}
+ data-sveltekit-preload-code="eager"
+ data-sveltekit-preload-data="false"
+ onclick={hideMenu}
+ >
+ <button
+ class="flex justify-center items-center font-semibold hover:opacity-80 gap-2"
>
- <button
- class="flex justify-center items-center font-semibold hover:opacity-80 gap-2"
- >
- <Icon width="32" />
- {t(key)}
- </button>
- </a>
- {/if}
- </li>
- {/each}
- </ul>
- <hr class="my-4" />
- <a href="/?stay=true" aria-label="Coinos home">
- <CoinosLogo width="160" />
- </a>
- </div>
- </OutClick>
+ <Icon width="32" />
+ {t(key)}
+ </button>
+ </a>
+ {/if}
+ </li>
+ {/each}
+ </ul>
+ <hr class="my-4" />
+ <a href="/?stay=true" aria-label="Coinos home">
+ <CoinosLogo width="160" />
+ </a>
+ </div>
</div>
-
diff --git a/src/components/Payments.svelte b/src/components/Payments.svelte
index 881da11d..2ebe9794 100644
--- a/src/components/Payments.svelte
+++ b/src/components/Payments.svelte
@@ -3,10 +3,8 @@
import LogosBitcoin from "virtual:icons/logos/bitcoin";
import { goto } from "$app/navigation";
import Avatar from "$comp/Avatar.svelte";
- import { get, f, s, si, sat, loc, sats, types } from "$lib/utils";
- import { format } from "date-fns";
+ import { get, f, s, si, sat, loc, sats, types, formatDate } from "$lib/utils";
import { t } from "$lib/translations";
- import locales from "$lib/locales";
import { fiat } from "$lib/store";
const { fund = undefined, locale, user, payments }: any = $props();
const language = $derived(user?.language || "en");
@@ -102,14 +100,10 @@
<div class="text-secondary text-right text-sm my-auto col-span-3">
<div>
- {format(new Date(p.created), "MMM d, yy", {
- locale: locales[language],
- })}
+ {formatDate(new Date(p.created), language, { month: "short", day: "numeric", year: "2-digit" })}
</div>
<div>
- {format(new Date(p.created), "h:mm aaa", {
- locale: locales[language],
- })}
+ {formatDate(new Date(p.created), language, { hour: "numeric", minute: "2-digit" })}
</div>
</div>
</div>
diff --git a/src/components/Qr.svelte b/src/components/Qr.svelte
index d5dbfc41..692f665e 100644
--- a/src/components/Qr.svelte
+++ b/src/components/Qr.svelte
@@ -1,14 +1,9 @@
<script lang="ts">
- import { onMount } from "svelte";
- import { browser } from "$app/environment";
let { icon = "", text }: any = $props();
let qr = $state();
- let screenfull;
- onMount(async () => {
- if (!browser) return;
- screenfull = (await import("screenfull")).default;
- });
+ const toggleFullscreen = (el) =>
+ document.fullscreenElement ? document.exitFullscreen() : el.requestFullscreen();
let src = $derived.by(() => {
let url = `/qr/${encodeURIComponent(text)}`;
@@ -21,8 +16,8 @@
<div
class="w-72 sm:w-80 mx-auto cursor-pointer"
bind:this={qr}
- onclick={() => screenfull?.toggle?.(qr)}
- onkeydown={(e) => (e.key === "Enter" || e.key === " ") && screenfull?.toggle?.(qr)}
+ onclick={() => toggleFullscreen(qr)}
+ onkeydown={(e) => (e.key === "Enter" || e.key === " ") && toggleFullscreen(qr)}
role="button"
tabindex="0"
aria-label="Toggle fullscreen QR"
diff --git a/src/lib/locales.ts b/src/lib/locales.ts
deleted file mode 100644
index 83e7a1bf..00000000
--- a/src/lib/locales.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { de } from "date-fns/locale/de";
-import { el } from "date-fns/locale/el";
-import { enUS as en } from "date-fns/locale/en-US";
-import { es } from "date-fns/locale/es";
-import { faIR as fa } from "date-fns/locale/fa-IR";
-import { fr } from "date-fns/locale/fr";
-import { ja } from "date-fns/locale/ja";
-import { pt } from "date-fns/locale/pt";
-import { ru } from "date-fns/locale/ru";
-import { zhCN as zh } from "date-fns/locale/zh-CN";
-import { arSA as ar } from "date-fns/locale/ar-SA";
-import { hi } from "date-fns/locale/hi";
-import { bn } from "date-fns/locale/bn";
-import { tr } from "date-fns/locale/tr";
-import { ko } from "date-fns/locale/ko";
-import { it } from "date-fns/locale/it";
-import { nl } from "date-fns/locale/nl";
-import { th } from "date-fns/locale/th";
-import { pl } from "date-fns/locale/pl";
-
-export default {
- de,
- el,
- en,
- es,
- fa,
- fr,
- ja,
- pt,
- ru,
- zh,
- ar,
- hi,
- bn,
- tr,
- ko,
- it,
- nl,
- th,
- pl,
-};
diff --git a/src/lib/random.ts b/src/lib/random.ts
index 4c8dbda3..73afa443 100644
--- a/src/lib/random.ts
+++ b/src/lib/random.ts
@@ -1,15 +1,17 @@
-import { NumberDictionary, animals, colors, uniqueNamesGenerator } from "unique-names-generator";
+const animals = [
+ "alligator", "bear", "cat", "dog", "eagle", "falcon", "gorilla", "hawk",
+ "iguana", "jaguar", "koala", "lion", "moose", "newt", "otter", "penguin",
+ "quail", "rabbit", "shark", "tiger", "urchin", "viper", "walrus", "fox",
+ "yak", "zebra", "badger", "crane", "dolphin", "elk",
+];
-export const randomName = () =>
- uniqueNamesGenerator({
- dictionaries: [animals, NumberDictionary.generate({ min: 10, max: 99 })],
- length: 2,
- separator: "",
- });
+const colors = [
+ "red", "blue", "green", "gold", "silver", "coral", "amber", "violet",
+ "teal", "crimson", "ivory", "jade", "navy", "olive", "scarlet",
+];
-export const randomPassword = () =>
- uniqueNamesGenerator({
- dictionaries: [colors, NumberDictionary.generate({ min: 100, max: 999 })],
- length: 2,
- separator: "",
- });
+const pick = (arr: string[]) => arr[Math.floor(Math.random() * arr.length)];
+const randInt = (min: number, max: number) => min + Math.floor(Math.random() * (max - min + 1));
+
+export const randomName = () => pick(animals) + randInt(10, 99);
+export const randomPassword = () => pick(colors) + randInt(100, 999);
diff --git a/src/lib/socket.ts b/src/lib/socket.ts
index 46784503..b2d070fe 100644
--- a/src/lib/socket.ts
+++ b/src/lib/socket.ts
@@ -3,8 +3,7 @@ import { navigating, page } from "$app/stores";
import { PUBLIC_SOCKET } from "$env/static/public";
import { vaultForwarding } from "$lib/ark";
import { event, importing, invoice, last, lastPayment, paymentSignal, request } from "$lib/store";
-import { s, sleep, success, wait } from "$lib/utils";
-import cookies from "js-cookie";
+import { getCookie, s, sleep, success, wait } from "$lib/utils";
import { get } from "svelte/store";
export let socket;
@@ -61,7 +60,7 @@ export const messages = (data) => ({
url: { pathname },
} = get(page);
- const username = cookies.get("username");
+ const username = getCookie("username");
if (amount > 0 && !vaultForwarding) {
if (
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 7a4030d5..6815a5b2 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -6,12 +6,7 @@ import { sha256 } from "@noble/hashes/sha2.js";
import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils.js";
import { fail as svelteFail, redirect } from "@sveltejs/kit";
import { toast } from "@zerodevx/svelte-toast";
-import {
- differenceInDays,
- differenceInHours,
- differenceInMinutes,
- differenceInSeconds,
-} from "date-fns";
+
import { get as getStore } from "svelte/store";
export function scroll(section: any) {
@@ -484,20 +479,23 @@ export const versions = {
export const str = (s) => s.toString();
-export const ago = (t) => {
- const now = new Date();
- const date = new Date(t * 1000);
- const seconds = differenceInSeconds(now, date);
- if (seconds < 60) return `${seconds}s`;
-
- const minutes = differenceInMinutes(now, date);
- if (minutes < 60) return `${minutes}m`;
+const localeTagMap: Record<string, string> = {
+ en: "en-US",
+ fa: "fa-IR",
+ zh: "zh-CN",
+ ar: "ar-SA",
+};
+export const toLocaleTag = (lang = "en") => localeTagMap[lang] || lang;
- const hours = differenceInHours(now, date);
- if (hours < 24) return `${hours}h`;
+export const formatDate = (date: Date, lang = "en", opts: Intl.DateTimeFormatOptions = {}) =>
+ new Intl.DateTimeFormat(toLocaleTag(lang), opts).format(date);
- const days = differenceInDays(now, date);
- return `${days}d`;
+export const ago = (t) => {
+ const diff = Math.floor((Date.now() - t * 1000) / 1000);
+ if (diff < 60) return `${diff}s`;
+ if (diff < 3600) return `${Math.floor(diff / 60)}m`;
+ if (diff < 86400) return `${Math.floor(diff / 3600)}h`;
+ return `${Math.floor(diff / 86400)}d`;
};
export const register = async (
diff --git a/src/routes/(app)/[username]/(profile)/+page.ts b/src/routes/(app)/[username]/(profile)/+page.ts
index e6a3ffeb..f60bee57 100644
--- a/src/routes/(app)/[username]/(profile)/+page.ts
+++ b/src/routes/(app)/[username]/(profile)/+page.ts
@@ -1,9 +1,9 @@
import { signer } from "$lib/store";
-import cookies from "js-cookie";
+import { getCookie } from "$lib/utils";
import { get } from "svelte/store";
export const ssr = false;
export async function load() {
- const sk = cookies.get("sk");
+ const sk = getCookie("sk");
if (sk && !get(signer)) signer.set({ method: "nsec", params: { sk }, ready: true });
}
diff --git a/src/routes/(app)/[username]/accepted/[text]/raw/+server.ts b/src/routes/(app)/[username]/accepted/[text]/raw/+server.ts
index ad7fc6b1..77bb8a09 100644
--- a/src/routes/(app)/[username]/accepted/[text]/raw/+server.ts
+++ b/src/routes/(app)/[username]/accepted/[text]/raw/+server.ts
@@ -1,15 +1,13 @@
-import Qr from "qrcode-base64";
+import QRCode from "qrcode";
export async function GET({ params }) {
const { text } = params;
- const dataUri = Qr.drawImg(text, { size: 600 });
- const base64Data = dataUri.split(",")[1];
- const binaryData = Buffer.from(base64Data, "base64");
+ const buffer = await QRCode.toBuffer(text, { width: 600, type: "png" });
- return new Response(binaryData, {
+ return new Response(buffer, {
headers: {
- "Content-Type": "image/gif",
+ "Content-Type": "image/png",
"Cache-Control": "public, max-age=31536000, immutable",
},
});
diff --git a/src/routes/(app)/fund/[id]/+page.svelte b/src/routes/(app)/fund/[id]/+page.svelte
index 94d768aa..dea5a19b 100644
--- a/src/routes/(app)/fund/[id]/+page.svelte
+++ b/src/routes/(app)/fund/[id]/+page.svelte
@@ -7,7 +7,6 @@
import PhLightningFill from "virtual:icons/ph/lightning-fill";
import Amount from "$comp/Amount.svelte";
import Payments from "$comp/Payments.svelte";
- import { format } from "date-fns";
import { enhance } from "$app/forms";
import { page } from "$app/stores";
import Avatar from "$comp/Avatar.svelte";
diff --git a/src/routes/(app)/payment/[id]/+page.svelte b/src/routes/(app)/payment/[id]/+page.svelte
index 55daca8d..3e8c4788 100644
--- a/src/routes/(app)/payment/[id]/+page.svelte
+++ b/src/routes/(app)/payment/[id]/+page.svelte
@@ -5,7 +5,7 @@
import { browser } from "$app/environment";
import { onMount, tick } from "svelte";
import { t, loading } from "$lib/translations";
- import { copy, f, s, loc, toFiat, post, sats, fail, success, types } from "$lib/utils";
+ import { copy, f, s, loc, toFiat, post, sats, fail, success, types, formatDate } from "$lib/utils";
import { fiat } from "$lib/store";
const toggleFiat = (e) => {
@@ -14,9 +14,7 @@
$fiat = !$fiat;
};
import Avatar from "$comp/Avatar.svelte";
- import { format } from "date-fns";
import { PUBLIC_EXPLORER, PUBLIC_LIQUID_EXPLORER } from "$env/static/public";
- import locales from "$lib/locales";
import { goto } from "$app/navigation";
let expanded: Set<string> = $state(new Set());
@@ -24,7 +22,6 @@
let { data } = $props();
let user = $derived(data.user);
let p = $derived(data.payment);
- let locale = $derived(user ? locales[user.language] : locales["en"]);
let userLocale = $derived(loc(user));
let {
@@ -192,7 +189,7 @@
</span>
</button>
<div class="text-secondary">
- {format(new Date(created), "MMM d, yyyy", { locale })}<span class="mx-3">{format(new Date(created), "h:mmaaa", { locale })}</span>
+ {formatDate(new Date(created), user?.language, { month: "short", day: "numeric", year: "numeric" })}<span class="mx-3">{formatDate(new Date(created), user?.language, { hour: "numeric", minute: "2-digit" })}</span>
</div>
</div>
diff --git a/src/routes/(app)/payment/[id]/plain/+page.svelte b/src/routes/(app)/payment/[id]/plain/+page.svelte
index 1efe2c32..d92ab58f 100644
--- a/src/routes/(app)/payment/[id]/plain/+page.svelte
+++ b/src/routes/(app)/payment/[id]/plain/+page.svelte
@@ -3,10 +3,9 @@
import { onMount } from "svelte";
import { browser } from "$app/environment";
import { t } from "$lib/translations";
- import { back, copy, f, s, toFiat, post, sats, success, types } from "$lib/utils";
+ import { back, copy, f, s, toFiat, post, sats, success, types, formatDate } from "$lib/utils";
import { fiat } from "$lib/store";
import Avatar from "$comp/Avatar.svelte";
- import { format } from "date-fns";
import { PUBLIC_EXPLORER as expl } from "$env/static/public";
let { data } = $props();
@@ -66,7 +65,7 @@
<div>
<span class="text-lg text-secondary">Date</span>
- <div>{format(new Date(created), "MMMM d")}, {format(new Date(created), "h:mm aaa")}</div>
+ <div>{formatDate(new Date(created), "en", { month: "long", day: "numeric" })}, {formatDate(new Date(created), "en", { hour: "numeric", minute: "2-digit" })}</div>
</div>
{#if type === "bitcoin"}
diff --git a/src/routes/(app)/payments/[...page]/+page.svelte b/src/routes/(app)/payments/[...page]/+page.svelte
index cbe5d07c..c34f04fe 100644
--- a/src/routes/(app)/payments/[...page]/+page.svelte
+++ b/src/routes/(app)/payments/[...page]/+page.svelte
@@ -3,12 +3,10 @@
import Avatar from "$comp/Avatar.svelte";
import Payments from "$comp/Payments.svelte";
import { onMount } from "svelte";
- import { format } from "date-fns";
import { newPayment, cachedPayments } from "$lib/store";
import { t } from "$lib/translations";
import { get, f, s, si, sat, loc, sats, types } from "$lib/utils";
import { page } from "$app/stores";
- import { differenceInDays, getUnixTime, sub } from "date-fns";
import { goto, invalidate } from "$app/navigation";
let { data } = $props();
@@ -26,28 +24,28 @@
let presets = $derived([
{
title: $t("payments.day"),
- start: sub(new Date(), { days: 1 }),
+ start: new Date(Date.now() - 86400000),
end: null,
},
{
title: $t("payments.week"),
- start: sub(new Date(), { days: 7 }),
+ start: new Date(Date.now() - 7 * 86400000),
end: null,
},
{
title: $t("payments.month"),
- start: sub(new Date(), { months: 1 }),
+ start: new Date(Date.now() - 30 * 86400000),
end: null,
},
{
title: $t("payments.all"),
- start: sub(new Date(), { years: 5 }),
+ start: new Date(Date.now() - 5 * 365 * 86400000),
end: null,
},
]);
let selection = $derived(
- presets.findIndex((p) => Math.abs(differenceInDays(new Date(start * 1000), p.start)) < 1),
+ presets.findIndex((p) => Math.abs(new Date(start * 1000).getTime() - p.start.getTime()) < 86400000),
);
$effect(() => {
@@ -158,7 +156,7 @@
<div class="flex w-full gap-1">
{#each presets as { start, end, title }, i}
<a
- href={`/payments/${getUnixTime(start)}/1`}
+ href={`/payments/${Math.floor(start.getTime() / 1000)}/1`}
class="btn !w-auto flex-1"
class:!btn-active={selection === i}
>
diff --git a/src/routes/(app)/qr/[text]/raw/+server.ts b/src/routes/(app)/qr/[text]/raw/+server.ts
index ad7fc6b1..77bb8a09 100644
--- a/src/routes/(app)/qr/[text]/raw/+server.ts
+++ b/src/routes/(app)/qr/[text]/raw/+server.ts
@@ -1,15 +1,13 @@
-import Qr from "qrcode-base64";
+import QRCode from "qrcode";
export async function GET({ params }) {
const { text } = params;
- const dataUri = Qr.drawImg(text, { size: 600 });
- const base64Data = dataUri.split(",")[1];
- const binaryData = Buffer.from(base64Data, "base64");
+ const buffer = await QRCode.toBuffer(text, { width: 600, type: "png" });
- return new Response(binaryData, {
+ return new Response(buffer, {
headers: {
- "Content-Type": "image/gif",
+ "Content-Type": "image/png",
"Cache-Control": "public, max-age=31536000, immutable",
},
});
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
index 719e35d6..0fcf5ec8 100644
--- a/src/routes/+layout.ts
+++ b/src/routes/+layout.ts
@@ -1,11 +1,7 @@
import { browser } from "$app/environment";
import { theme as themeStore } from "$lib/store";
import { addTranslations, setLocale, setRoute } from "$lib/translations/index";
-import cookies from "js-cookie";
-
-const expires = new Date();
-expires.setSeconds(expires.getSeconds() + 21000000);
-const opts = { path: "/", expires };
+import { getCookie, setCookie } from "$lib/utils";
/** @type {import('@sveltejs/kit').Load} */
export const load = async ({ data }) => {
@@ -18,12 +14,12 @@ export const load = async ({ data }) => {
await setLocale(locale);
if (browser) {
- let theme = cookies.get("theme");
+ let theme = getCookie("theme");
if (!theme) {
theme = matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
- cookies.set("theme", theme, opts);
+ setCookie("theme", theme, 21000000);
if (theme === "dark") setTimeout(() => themeStore.set(theme), 100);
}