Browse Source

Allow for publications to be found with naddr or event, and not only d-tags. Prettified the json formatting in the View JSON window. Change the remaining blank links to buttons. Refactored.

Closes#194
master
Silberengel 11 months ago
parent
commit
2ca9014702
  1. 9
      src/lib/components/PublicationHeader.svelte
  2. 41
      src/lib/components/util/CardActions.svelte
  3. 4
      src/lib/components/util/CopyToClipboard.svelte
  4. 12
      src/lib/components/util/Profile.svelte
  5. 14
      src/lib/utils.ts
  6. 103
      src/routes/publication/+page.ts

9
src/lib/components/PublicationHeader.svelte

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
<script lang="ts">
import { ndkInstance } from '$lib/ndk';
import { neventEncode } from '$lib/utils';
import { naddrEncode } from '$lib/utils';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import { standardRelays } from '../consts';
import { Card, Img } from "flowbite-svelte";
@ -16,11 +16,12 @@ @@ -16,11 +16,12 @@
const href = $derived.by(() => {
const d = event.getMatchingTags('d')[0]?.[1];
if (d != null) {
return `publication?d=${d}`;
return `publication?d=${d}`;
} else {
return `publication?id=${neventEncode(event, relays)}`;
return `publication?id=${naddrEncode(event, relays)}`;
}
});
}
);
let title: string = $derived(event.getMatchingTags('title')[0]?.[1]);
let author: string = $derived(event.getMatchingTags('author')[0]?.[1] ?? 'unknown');

41
src/lib/components/util/CardActions.svelte

@ -9,8 +9,7 @@ @@ -9,8 +9,7 @@
} from "flowbite-svelte-icons";
import { Button, Modal, Popover } from "flowbite-svelte";
import { standardRelays } from "$lib/consts";
import { neventEncode } from "$lib/utils";
import { type AddressPointer, naddrEncode } from "nostr-tools/nip19";
import { neventEncode, naddrEncode } from "$lib/utils";
import InlineProfile from "$components/util/InlineProfile.svelte";
let { event } = $props();
@ -45,16 +44,9 @@ @@ -45,16 +44,9 @@
function shareNjump() {
const relays: string[] = standardRelays;
const dTag : string | undefined = event.dTag;
if (typeof dTag === 'string') {
const opts: AddressPointer = {
identifier: dTag,
pubkey: event.pubkey,
kind: 30040,
relays
};
const naddr = naddrEncode(opts);
try {
const naddr = naddrEncode(event, relays);
console.debug(naddr);
navigator.clipboard.writeText(`https://njump.me/${naddr}`);
shareLinkCopied = true;
@ -62,9 +54,8 @@ @@ -62,9 +54,8 @@
shareLinkCopied = false;
}, 4000);
}
else {
console.log('dTag is undefined');
catch (e) {
console.error('Failed to encode naddr:', e);
}
}
@ -114,32 +105,32 @@ @@ -114,32 +105,32 @@
<div class='flex flex-col text-nowrap'>
<ul class="space-y-2">
<li>
<a href="" role="button" class='btn-leather' onclick={viewDetails}>
<button class='btn-leather w-full text-left' onclick={viewDetails}>
<EyeOutline class="inline mr-2" /> View details
</a>
</button>
</li>
<li>
<a role="button" class='btn-leather' onclick={shareNjump}>
<button class='btn-leather w-full text-left' onclick={shareNjump}>
{#if shareLinkCopied}
<ClipboardCheckOutline class="inline mr-2" /> Copied!
{:else}
<ShareNodesOutline class="inline mr-2" /> Share via NJump
{/if}
</a>
</button>
</li>
<li>
<a role="button" class='btn-leather' onclick={copyEventId}>
<button class='btn-leather w-full text-left' onclick={copyEventId}>
{#if eventIdCopied}
<ClipboardCheckOutline class="inline mr-2" /> Copied!
{:else}
<ClipboardCleanOutline class="inline mr-2" /> Copy event ID
{/if}
</a>
</button>
</li>
<li>
<a href="" role="button" class='btn-leather' onclick={viewJson}>
<button class='btn-leather w-full text-left' onclick={viewJson}>
<CodeOutline class="inline mr-2" /> View JSON
</a>
</button>
</li>
</ul>
</div>
@ -149,7 +140,7 @@ @@ -149,7 +140,7 @@
<!-- Event JSON -->
<Modal class='modal-leather' title='Event JSON' bind:open={jsonModalOpen} autoclose outsideclose size='sm'>
<div class="overflow-auto bg-highlight dark:bg-primary-900 text-sm rounded p-1">
<code>{JSON.stringify(event.rawEvent())}</code>
<pre><code>{JSON.stringify(event.rawEvent(), null, 2)}</code></pre>
</div>
</Modal>
<!-- Event details -->
@ -157,7 +148,7 @@ @@ -157,7 +148,7 @@
<div class="flex flex-row space-x-4">
{#if image}
<div class="flex col">
<img class="max-w-48" src={image} />
<img class="max-w-48" src={image} alt="Publication cover" />
</div>
{/if}
<div class="flex flex-col col space-y-5 justify-center align-middle">

4
src/lib/components/util/CopyToClipboard.svelte

@ -18,10 +18,10 @@ @@ -18,10 +18,10 @@
}
</script>
<a role="button" class='btn-leather text-nowrap' onclick={copyToClipboard}>
<button class='btn-leather text-nowrap' onclick={copyToClipboard}>
{#if copied}
<ClipboardCheckOutline class="!fill-none dark:!fill-none inline mr-1" /> Copied!
{:else}
<ClipboardCleanOutline class="!fill-none dark:!fill-none inline mr-1" /> {displayText}
{/if}
</a>
</button>

12
src/lib/components/util/Profile.svelte

@ -70,25 +70,21 @@ function shortenNpub(long: string|undefined) { @@ -70,25 +70,21 @@ function shortenNpub(long: string|undefined) {
</li>
{#if isNav}
<li>
<a
href=""
<button
id='sign-out-button'
class='btn-leather text-nowrap mt-3 flex self-stretch align-middle hover:text-primary-400 dark:hover:text-primary-500'
onclick={handleSignOutClick}
role="button"
>
<ArrowRightToBracketOutline class='mr-1 !h-6 !w-6 inline !fill-none dark:!fill-none' /> Sign out
</a>
</button>
</li>
{:else}
<!-- li>
<a
href=""
<button
class='btn-leather text-nowrap mt-3 flex self-stretch align-middle hover:text-primary-400 dark:hover:text-primary-500'
role="button"
>
<FileSearchOutline class='mr-1 !h-6 inline !fill-none dark:!fill-none' /> More content
</a>
</button>
</li -->
{/if}
</ul>

14
src/lib/utils.ts

@ -10,6 +10,20 @@ export function neventEncode(event: NDKEvent, relays: string[]) { @@ -10,6 +10,20 @@ export function neventEncode(event: NDKEvent, relays: string[]) {
});
}
export function naddrEncode(event: NDKEvent, relays: string[]) {
const dTag = event.getMatchingTags('d')[0]?.[1];
if (!dTag) {
throw new Error('Event does not have a d tag');
}
return nip19.naddrEncode({
identifier: dTag,
pubkey: event.pubkey,
kind: event.kind || 0,
relays,
});
}
export function formatDate(unixtimestamp: number) {
const months = [
"Jan",

103
src/routes/publication/+page.ts

@ -1,43 +1,90 @@ @@ -1,43 +1,90 @@
import { error } from '@sveltejs/kit';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import type { PageLoad } from './$types';
import { nip19 } from 'nostr-tools';
import { getActiveRelays } from '$lib/ndk.ts';
import { setContext } from 'svelte';
import { PublicationTree } from '$lib/data_structures/publication_tree.ts';
/**
* Decodes an naddr identifier and returns a filter object
*/
function decodeNaddr(id: string) {
try {
if (!id.startsWith('naddr1')) return {};
const decoded = nip19.decode(id);
if (decoded.type !== 'naddr') return {};
const data = decoded.data;
return {
kinds: [data.kind],
authors: [data.pubkey],
'#d': [data.identifier]
};
} catch (e) {
console.error('Failed to decode naddr:', e);
return {};
}
}
/**
* Fetches an event by ID or filter
*/
async function fetchEventById(ndk: any, id: string): Promise<NDKEvent> {
const filter = decodeNaddr(id);
const hasFilter = Object.keys(filter).length > 0;
try {
const event = await (hasFilter ?
ndk.fetchEvent(filter) :
ndk.fetchEvent(id));
if (!event) {
throw new Error(`Event not found for ID: ${id}`);
}
return event;
} catch (err) {
throw error(404, `Failed to fetch publication root event for ID: ${id}\n${err}`);
}
}
/**
* Fetches an event by d tag
*/
async function fetchEventByDTag(ndk: any, dTag: string): Promise<NDKEvent> {
try {
const event = await ndk.fetchEvent(
{ '#d': [dTag] },
{ closeOnEose: false },
getActiveRelays(ndk)
);
if (!event) {
throw new Error(`Event not found for d tag: ${dTag}`);
}
return event;
} catch (err) {
throw error(404, `Failed to fetch publication root event for d tag: ${dTag}\n${err}`);
}
}
export const load: PageLoad = async ({ url, parent }: { url: URL; parent: () => Promise<any> }) => {
const id = url.searchParams.get('id');
const dTag = url.searchParams.get('d');
const { ndk, parser } = await parent();
let eventPromise: Promise<NDKEvent | null>;
let indexEvent: NDKEvent | null;
if (id) {
eventPromise = ndk.fetchEvent(id)
.then((ev: NDKEvent | null) => {
return ev;
})
.catch((err: any) => {
error(404, `Failed to fetch publication root event for ID: ${id}\n${err}`);
});
} else if (dTag) {
eventPromise = new Promise<NDKEvent | null>(resolve => {
ndk
.fetchEvent({ '#d': [dTag] }, { closeOnEose: false }, getActiveRelays(ndk))
.then((event: NDKEvent | null) => {
resolve(event);
})
.catch((err: any) => {
error(404, `Failed to fetch publication root event for d tag: ${dTag}\n${err}`);
});
});
} else {
error(400, 'No publication root event ID or d tag provided.');
if (!id && !dTag) {
throw error(400, 'No publication root event ID or d tag provided.');
}
indexEvent = await eventPromise as NDKEvent;
// Fetch the event based on available parameters
const indexEvent = id
? await fetchEventById(ndk, id)
: await fetchEventByDTag(ndk, dTag!);
const publicationType = indexEvent?.getMatchingTags('type')[0]?.[1];
const fetchPromise = parser.fetch(indexEvent);

Loading…
Cancel
Save