diff --git a/src/lib/components/EventMenu.svelte b/src/lib/components/EventMenu.svelte index 3b7acde..8e82ab0 100644 --- a/src/lib/components/EventMenu.svelte +++ b/src/lib/components/EventMenu.svelte @@ -271,6 +271,8 @@ function viewEvent() { closeMenu(); + // Store event in sessionStorage so the event page can use it without re-fetching + sessionStorage.setItem('aitherboard_preloadedEvent', JSON.stringify(event)); goto(getEventLink(event)); } diff --git a/src/lib/components/content/EmbeddedEventBlurb.svelte b/src/lib/components/content/EmbeddedEventBlurb.svelte index 9953389..ced6eac 100644 --- a/src/lib/components/content/EmbeddedEventBlurb.svelte +++ b/src/lib/components/content/EmbeddedEventBlurb.svelte @@ -168,6 +168,8 @@ + {#if hasMedia} + + {/if} @@ -809,7 +809,7 @@

{event.content.substring(0, 200)}{event.content.length > 200 ? '...' : ''}

- View + { e.preventDefault(); sessionStorage.setItem('aitherboard_preloadedEvent', JSON.stringify(event)); goto(`/event/${event.id}`); }} class="action-button">View diff --git a/src/routes/discussions/+page.svelte b/src/routes/discussions/+page.svelte index 78c6774..b964392 100644 --- a/src/routes/discussions/+page.svelte +++ b/src/routes/discussions/+page.svelte @@ -10,6 +10,7 @@ import type { NostrEvent } from '../../lib/types/nostr.js'; import { onMount } from 'svelte'; import { page } from '$app/stores'; + import { goto } from '$app/navigation'; import Pagination from '../../lib/components/ui/Pagination.svelte'; import { getPaginatedItems, getCurrentPage, ITEMS_PER_PAGE } from '../../lib/utils/pagination.js'; import Icon from '../../lib/components/ui/Icon.svelte'; @@ -126,7 +127,7 @@

Events ({searchResults.events.length})

{#each paginatedSearchEvents as event} - + { e.preventDefault(); sessionStorage.setItem('aitherboard_preloadedEvent', JSON.stringify(event)); goto(`/event/${event.id}`); }} class="event-result-card"> {/each} diff --git a/src/routes/event/[id]/+page.svelte b/src/routes/event/[id]/+page.svelte index 7b903d8..b11a74e 100644 --- a/src/routes/event/[id]/+page.svelte +++ b/src/routes/event/[id]/+page.svelte @@ -9,23 +9,26 @@ import { page } from '$app/stores'; import { nip19 } from 'nostr-tools'; import { KIND } from '../../../lib/types/kind-lookup.js'; + import type { NostrEvent } from '../../../lib/types/nostr.js'; let decodedEventId = $state(null); let eventKind = $state(null); + let preloadedEvent = $state(null); // Store event if already loaded (e.g., from naddr) let loading = $state(false); let error = $state(null); let lastProcessedParam = $state(null); // Track last processed param to prevent loops /** - * Decode route parameter to event hex ID + * Decode route parameter to event hex ID and optionally return the event * Supports: hex event id, note, nevent, naddr + * Returns: { eventId: string, event?: NostrEvent } or null */ - async function decodeEventId(param: string): Promise { + async function decodeEventId(param: string): Promise<{ eventId: string; event?: NostrEvent } | null> { if (!param) return null; // Check if it's already a hex event ID (64 hex characters) if (/^[0-9a-f]{64}$/i.test(param)) { - return param.toLowerCase(); + return { eventId: param.toLowerCase() }; } // Check if it's a bech32 encoded format (note, nevent, naddr) @@ -33,11 +36,11 @@ try { const decoded = nip19.decode(param); if (decoded.type === 'note') { - return String(decoded.data); + return { eventId: String(decoded.data) }; } else if (decoded.type === 'nevent') { // nevent contains event id and optional relays if (decoded.data && typeof decoded.data === 'object' && 'id' in decoded.data) { - return String(decoded.data.id); + return { eventId: String(decoded.data.id) }; } } else if (decoded.type === 'naddr') { // naddr is for parameterized replaceable events (kind + pubkey + d tag) @@ -70,11 +73,12 @@ const events = await nostrClient.fetchEvents( filters, relays, - { useCache: true, cacheResults: true } + { useCache: 'cache-first', cacheResults: true, timeout: 10000 } ); if (events.length > 0) { - return events[0].id; + // Return both eventId and the event itself to avoid re-fetching + return { eventId: events[0].id, event: events[0] }; } else { // Event not found for naddr return null; @@ -103,20 +107,49 @@ error = null; decodedEventId = null; eventKind = null; + preloadedEvent = null; lastProcessedParam = currentParam; // Track that we're processing this param try { - const eventId = await decodeEventId(currentParam); - if (eventId) { - decodedEventId = eventId; + // Check sessionStorage for a preloaded event (from EventMenu, eye icon button, or any click) + let sessionEvent: NostrEvent | null = null; + if (typeof window !== 'undefined') { + const preloadedEventStr = sessionStorage.getItem('aitherboard_preloadedEvent'); + if (preloadedEventStr) { + try { + sessionEvent = JSON.parse(preloadedEventStr) as NostrEvent; + // Clear it after reading (we'll verify it matches first) + sessionStorage.removeItem('aitherboard_preloadedEvent'); + } catch (parseError) { + // Invalid JSON in sessionStorage, continue with normal loading + console.warn('Failed to parse preloaded event from sessionStorage:', parseError); + sessionStorage.removeItem('aitherboard_preloadedEvent'); + } + } + } + + const result = await decodeEventId(currentParam); + if (result) { + decodedEventId = result.eventId; - // Fetch the event to determine its kind for routing - const threadRelays = relayManager.getThreadReadRelays(); - const feedRelays = relayManager.getFeedReadRelays(); - const allRelays = [...new Set([...threadRelays, ...feedRelays])]; - const event = await nostrClient.getEventById(eventId, allRelays); - if (event) { - eventKind = event.kind; + // If we already have the event from naddr decoding, use it (highest priority) + if (result.event) { + preloadedEvent = result.event; + eventKind = result.event.kind; + } else if (sessionEvent && sessionEvent.id === result.eventId) { + // Use session event if it matches the decoded event ID + preloadedEvent = sessionEvent; + eventKind = sessionEvent.kind; + } else { + // Fetch the event to determine its kind for routing + const threadRelays = relayManager.getThreadReadRelays(); + const feedRelays = relayManager.getFeedReadRelays(); + const allRelays = [...new Set([...threadRelays, ...feedRelays])]; + const event = await nostrClient.getEventById(result.eventId, allRelays); + if (event) { + preloadedEvent = event; + eventKind = event.kind; + } } } else { error = 'Event not found or invalid format'; @@ -146,24 +179,33 @@
- {#if loading} - -

Loading event...

- {:else if error} - -

{error}

- {:else if decodedEventId} - - {#if eventKind === KIND.DISCUSSION_THREAD} - - +
+ {#if loading} + +

Loading event...

+ {:else if error} + +

{error}

+ {:else if decodedEventId} + + {#if eventKind === KIND.DISCUSSION_THREAD} + + + {:else} + + + {/if} + {:else if $page.params.id} +

Invalid event ID format. Supported: hex event ID, note, nevent, or naddr

{:else} - - +

Event ID required

{/if} - {:else if $page.params.id} -

Invalid event ID format. Supported: hex event ID, note, nevent, or naddr

- {:else} -

Event ID required

- {/if} +
+ + diff --git a/src/routes/find/+page.svelte b/src/routes/find/+page.svelte index 7e2b5ff..f3ab459 100644 --- a/src/routes/find/+page.svelte +++ b/src/routes/find/+page.svelte @@ -12,7 +12,7 @@ import { onMount } from 'svelte'; import { page } from '$app/stores'; import { untrack } from 'svelte'; - import { afterNavigate } from '$app/navigation'; + import { afterNavigate, goto } from '$app/navigation'; import Pagination from '../../lib/components/ui/Pagination.svelte'; import { getPaginatedItems, getCurrentPage, ITEMS_PER_PAGE } from '../../lib/utils/pagination.js'; @@ -156,7 +156,7 @@
{#each paginatedCacheEvents as event}
- + { e.preventDefault(); sessionStorage.setItem('aitherboard_preloadedEvent', JSON.stringify(event)); goto(`/event/${event.id}`); }} class="event-result-link">
@@ -194,7 +194,7 @@
{#each paginatedSearchEvents as event}
- + { e.preventDefault(); sessionStorage.setItem('aitherboard_preloadedEvent', JSON.stringify(event)); goto(`/event/${event.id}`); }} class="event-result-link"> {#if eventRelayMap.has(event.id)} diff --git a/src/routes/highlights/+page.svelte b/src/routes/highlights/+page.svelte index 59dd374..d3edd95 100644 --- a/src/routes/highlights/+page.svelte +++ b/src/routes/highlights/+page.svelte @@ -310,7 +310,7 @@ {#each searchResults.events as event} {#if event.kind === KIND.HIGHLIGHTED_ARTICLE}
- goto(`/event/${e.id}`)} /> + { sessionStorage.setItem('aitherboard_preloadedEvent', JSON.stringify(e)); goto(`/event/${e.id}`); }} />
{/if} {/each} @@ -337,7 +337,7 @@
{#each paginatedItems as item (item.event.id)}
- goto(`/event/${event.id}`)} /> + { sessionStorage.setItem('aitherboard_preloadedEvent', JSON.stringify(event)); goto(`/event/${event.id}`); }} />
{/each}
diff --git a/src/routes/profile/[pubkey]/+page.svelte b/src/routes/profile/[pubkey]/+page.svelte index 42ecf23..f21ce95 100644 --- a/src/routes/profile/[pubkey]/+page.svelte +++ b/src/routes/profile/[pubkey]/+page.svelte @@ -23,6 +23,15 @@
- - +
+ + +
+ + diff --git a/src/routes/repos/+page.svelte b/src/routes/repos/+page.svelte index ac33267..ae87bbd 100644 --- a/src/routes/repos/+page.svelte +++ b/src/routes/repos/+page.svelte @@ -563,7 +563,7 @@ {:else} - + { e.preventDefault(); sessionStorage.setItem('aitherboard_preloadedEvent', JSON.stringify(event)); goto(`/event/${event.id}`); }} class="event-result-card"> {/if} diff --git a/src/routes/repos/[naddr]/+page.svelte b/src/routes/repos/[naddr]/+page.svelte index 5ef844e..05970ff 100644 --- a/src/routes/repos/[naddr]/+page.svelte +++ b/src/routes/repos/[naddr]/+page.svelte @@ -1468,7 +1468,7 @@ diff --git a/src/routes/topics/+page.svelte b/src/routes/topics/+page.svelte index 4067868..50556e5 100644 --- a/src/routes/topics/+page.svelte +++ b/src/routes/topics/+page.svelte @@ -282,7 +282,7 @@

Events ({searchResults.events.length})