From c201135d9ad935f9768dab880aa91a8bc2d432f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nu=C5=A1a=20Puk=C5=A1i=C4=8D?= Date: Wed, 21 May 2025 20:31:43 +0200 Subject: [PATCH] Moved profile into a card, added lnurl and QR code --- package-lock.json | 218 +++++++++++++++++- package.json | 5 +- src/app.css | 1 + src/lib/components/EventDetails.svelte | 76 +----- src/lib/components/Preview.svelte | 2 +- src/lib/components/Publication.svelte | 2 +- .../{blog => cards}/BlogHeader.svelte | 0 src/lib/components/cards/ProfileHeader.svelte | 113 +++++++++ .../components/util/CopyToClipboard.svelte | 5 +- src/lib/components/util/QrCode.svelte | 17 ++ src/styles/events.css | 5 + 11 files changed, 368 insertions(+), 76 deletions(-) rename src/lib/components/{blog => cards}/BlogHeader.svelte (100%) create mode 100644 src/lib/components/cards/ProfileHeader.svelte create mode 100644 src/lib/components/util/QrCode.svelte create mode 100644 src/styles/events.css diff --git a/package-lock.json b/package-lock.json index 5d74252..b631ab9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,11 +14,13 @@ "@tailwindcss/forms": "0.5.x", "@tailwindcss/typography": "0.5.x", "asciidoctor": "3.0.x", + "bech32": "^2.0.0", "d3": "^7.9.0", "he": "1.2.x", "highlight.js": "^11.11.1", "node-emoji": "^2.2.0", - "nostr-tools": "2.10.x" + "nostr-tools": "2.10.x", + "qrcode": "^1.5.4" }, "devDependencies": { "@playwright/test": "^1.50.1", @@ -30,6 +32,7 @@ "@types/d3": "^7.4.3", "@types/he": "1.2.x", "@types/node": "22.x", + "@types/qrcode": "^1.5.5", "autoprefixer": "10.x", "eslint-plugin-svelte": "2.x", "flowbite": "2.x", @@ -1230,6 +1233,16 @@ "undici-types": "~6.21.0" } }, + "node_modules/@types/qrcode": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz", + "integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/resolve": { "version": "1.20.2", "dev": true, @@ -1561,6 +1574,12 @@ "version": "1.0.2", "license": "MIT" }, + "node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==", + "license": "MIT" + }, "node_modules/binary-extensions": { "version": "2.3.0", "license": "MIT", @@ -1673,6 +1692,15 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "license": "MIT", @@ -2236,6 +2264,15 @@ } } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deep-eql": { "version": "5.0.2", "dev": true, @@ -2278,6 +2315,12 @@ "version": "1.2.2", "license": "Apache-2.0" }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "license": "MIT" + }, "node_modules/dlv": { "version": "1.1.3", "license": "MIT" @@ -3910,6 +3953,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/package-json-from-dist": { "version": "1.0.1", "license": "BlueOak-1.0.0" @@ -3928,9 +3980,7 @@ }, "node_modules/path-exists": { "version": "4.0.0", - "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -4045,6 +4095,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/postcss": { "version": "8.5.3", "funding": [ @@ -4381,6 +4440,141 @@ "node": ">=6" } }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "license": "MIT", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qrcode/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/qrcode/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qrcode/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/qrcode/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "funding": [ @@ -4437,6 +4631,12 @@ "node": ">=0.10.0" } }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, "node_modules/resolve": { "version": "1.22.10", "license": "MIT", @@ -4565,6 +4765,12 @@ "node": ">=10" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, "node_modules/set-cookie-parser": { "version": "2.7.1", "dev": true, @@ -5567,6 +5773,12 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, "node_modules/why-is-node-running": { "version": "2.3.0", "dev": true, diff --git a/package.json b/package.json index 06ba05f..787d2e7 100644 --- a/package.json +++ b/package.json @@ -20,11 +20,13 @@ "@tailwindcss/forms": "0.5.x", "@tailwindcss/typography": "0.5.x", "asciidoctor": "3.0.x", + "bech32": "^2.0.0", "d3": "^7.9.0", "he": "1.2.x", "highlight.js": "^11.11.1", "node-emoji": "^2.2.0", - "nostr-tools": "2.10.x" + "nostr-tools": "2.10.x", + "qrcode": "^1.5.4" }, "devDependencies": { "@playwright/test": "^1.50.1", @@ -36,6 +38,7 @@ "@types/d3": "^7.4.3", "@types/he": "1.2.x", "@types/node": "22.x", + "@types/qrcode": "^1.5.5", "autoprefixer": "10.x", "eslint-plugin-svelte": "2.x", "flowbite": "2.x", diff --git a/src/app.css b/src/app.css index 32e232c..21e1a48 100644 --- a/src/app.css +++ b/src/app.css @@ -2,6 +2,7 @@ @import './styles/scrollbar.css'; @import './styles/publications.css'; @import './styles/visualize.css'; +@import "./styles/events.css"; /* Custom styles */ @layer base { diff --git a/src/lib/components/EventDetails.svelte b/src/lib/components/EventDetails.svelte index 463dcfa..d4ad2e1 100644 --- a/src/lib/components/EventDetails.svelte +++ b/src/lib/components/EventDetails.svelte @@ -6,8 +6,8 @@ import { neventEncode, naddrEncode, nprofileEncode } from "$lib/utils"; import { standardRelays } from "$lib/consts"; import type { NDKEvent } from '$lib/utils/nostrUtils'; - import { onMount } from "svelte"; import { getMatchingTags } from '$lib/utils/nostrUtils'; + import ProfileHeader from "$components/cards/ProfileHeader.svelte"; const { event, profile = null } = $props<{ event: NDKEvent; @@ -68,8 +68,6 @@
{#if event.kind !== 0 && getEventTitle(event)}

{getEventTitle(event)}

- {:else if event.kind === 0 && profile && profile.name} -

{profile.name}

{/if}
@@ -106,71 +104,8 @@
- Content: - {#if event.kind === 0} - {#if profile} -
-
- {#if profile.name} -
-
Name:
-
{profile.name}
-
- {/if} - {#if profile.display_name} -
-
Display Name:
-
{profile.display_name}
-
- {/if} - {#if profile.about} -
-
About:
-
{profile.about}
-
- {/if} - {#if profile.picture} -
-
Picture:
-
- Profile { (e.target as HTMLImageElement).src = '/favicon.png'; }} /> -
-
- {/if} - {#if profile.banner} -
-
Banner:
-
- Banner { (e.target as HTMLImageElement).src = '/favicon.png'; }} /> -
-
- {/if} - {#if profile.website} -
-
Website:
-
- {profile.website} -
-
- {/if} - {#if profile.lud16} -
-
Lightning Address:
-
{profile.lud16}
-
- {/if} - {#if profile.nip05} -
-
NIP-05:
-
{profile.nip05}
-
- {/if} -
-
- {:else} -
{event.content}
- {/if} - {:else} + {#if event.kind !== 0} + Content:
{@html showFullContent ? parsedContent : contentPreview} {#if !showFullContent && parsedContent.length > 250} @@ -180,6 +115,11 @@ {/if}
+ + {#if event.kind === 0} + + {/if} + {#if event.tags && event.tags.length}
diff --git a/src/lib/components/Preview.svelte b/src/lib/components/Preview.svelte index d25ac71..e7a3f29 100644 --- a/src/lib/components/Preview.svelte +++ b/src/lib/components/Preview.svelte @@ -4,7 +4,7 @@ import { CaretDownSolid, CaretUpSolid, EditOutline } from 'flowbite-svelte-icons'; import Self from './Preview.svelte'; import { contentParagraph, sectionHeading } from '$lib/snippets/PublicationSnippets.svelte'; - import BlogHeader from "./blog/BlogHeader.svelte"; + import BlogHeader from "$components/cards/BlogHeader.svelte"; // TODO: Fix move between parents. diff --git a/src/lib/components/Publication.svelte b/src/lib/components/Publication.svelte index 5df2fe4..f7e026f 100644 --- a/src/lib/components/Publication.svelte +++ b/src/lib/components/Publication.svelte @@ -18,7 +18,7 @@ import type { PublicationTree } from "$lib/data_structures/publication_tree"; import Details from "$components/util/Details.svelte"; import { publicationColumnVisibility } from "$lib/stores"; - import BlogHeader from "$components/blog/BlogHeader.svelte"; + import BlogHeader from "$components/cards/BlogHeader.svelte"; import Interactions from "$components/util/Interactions.svelte"; import TocToggle from "$components/util/TocToggle.svelte"; import { pharosInstance } from '$lib/parser'; diff --git a/src/lib/components/blog/BlogHeader.svelte b/src/lib/components/cards/BlogHeader.svelte similarity index 100% rename from src/lib/components/blog/BlogHeader.svelte rename to src/lib/components/cards/BlogHeader.svelte diff --git a/src/lib/components/cards/ProfileHeader.svelte b/src/lib/components/cards/ProfileHeader.svelte new file mode 100644 index 0000000..bee6f48 --- /dev/null +++ b/src/lib/components/cards/ProfileHeader.svelte @@ -0,0 +1,113 @@ + + +{#if profile} + +
+ {#if profile.banner} +
+ Profile banner { (e.target as HTMLImageElement).style.display = 'none';}} /> +
+ {/if} +
+ {#if profile.picture} + Profile avatar { (e.target as HTMLImageElement).src = '/favicon.png'; }} /> + {/if} + {@render userBadge(toNpub(event.pubkey) as string, profile.displayName || profile.name || event.pubkey)} +
+
+
+
+ {#if profile.name} +
+
Name:
+
{profile.name}
+
+ {/if} + {#if profile.displayName} +
+
Display Name:
+
{profile.displayName}
+
+ {/if} + {#if profile.about} +
+
About:
+
{profile.about}
+
+ {/if} + {#if profile.website} +
+
Website:
+
+ {profile.website} +
+
+ {/if} + {#if profile.nip05} +
+
NIP-05:
+
{profile.nip05}
+
+ {/if} + {#if profile.lud16} +
+
Lightning Address:
+
+
+ {/if} +
+
+
+
+
+ + + {#if profile.lud16} +
+
+ {@render userBadge(toNpub(event.pubkey) as string, profile?.displayName || profile.name || event.pubkey)} +

{profile.lud16}

+
+
+

Scan the QR code or copy the address

+ {#if lnurl} +

+ +

+ + {:else} +

Couldn't generate address.

+ {/if} +
+
+ {/if} +
+{/if} \ No newline at end of file diff --git a/src/lib/components/util/CopyToClipboard.svelte b/src/lib/components/util/CopyToClipboard.svelte index cb49a6b..19c9850 100644 --- a/src/lib/components/util/CopyToClipboard.svelte +++ b/src/lib/components/util/CopyToClipboard.svelte @@ -1,11 +1,12 @@ + + diff --git a/src/styles/events.css b/src/styles/events.css new file mode 100644 index 0000000..9e8c202 --- /dev/null +++ b/src/styles/events.css @@ -0,0 +1,5 @@ +@layer components { + canvas.qr-code { + @apply block mx-auto my-4; + } +} \ No newline at end of file