From 1b5d861349aedc9a1ddcaf08111b36b5a0cec5b6 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Fri, 27 Mar 2026 21:21:17 +0100 Subject: [PATCH] pass reply-to event when opening the side-panel --- src/components/Embedded/EmbeddedNote.tsx | 3 ++- src/components/Note/index.tsx | 12 +++++++++--- src/components/NoteCard/MainNoteCard.tsx | 3 ++- src/components/ParentNotePreview/index.tsx | 1 + src/components/ReplyNote/index.tsx | 3 ++- src/components/ReplyNoteList/index.tsx | 12 +++++++++++- src/lib/navigation-related-events.ts | 20 ++++++++++++++++++++ src/services/client-events.service.ts | 10 ++++++++++ src/services/client.service.ts | 4 ++++ 9 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 src/lib/navigation-related-events.ts diff --git a/src/components/Embedded/EmbeddedNote.tsx b/src/components/Embedded/EmbeddedNote.tsx index 2b0dd23d..7a8cec73 100644 --- a/src/components/Embedded/EmbeddedNote.tsx +++ b/src/components/Embedded/EmbeddedNote.tsx @@ -19,6 +19,7 @@ import logger from '@/lib/logger' import { extractBookMetadata } from '@/lib/bookstr-parser' import { contentParserService } from '@/services/content-parser.service' import { useSmartNoteNavigationOptional } from '@/PageManager' +import { getCachedThreadContextEvents } from '@/lib/navigation-related-events' import { toNote } from '@/lib/link' import { type EmbeddedNoteIdValidation, @@ -597,7 +598,7 @@ function EmbeddedBookstrEvent({ event, originalNoteId, className }: { event: Eve } e.stopPropagation() const noteUrl = toNote(originalNoteId ?? event) - navigateToNote(noteUrl, event) + navigateToNote(noteUrl, event, getCachedThreadContextEvents(event)) }} > {/* Header */} diff --git a/src/components/Note/index.tsx b/src/components/Note/index.tsx index 8f095bc2..9b215930 100644 --- a/src/components/Note/index.tsx +++ b/src/components/Note/index.tsx @@ -8,6 +8,7 @@ import { isNip25ReactionKind, isNsfwEvent } from '@/lib/event' +import { getCachedThreadContextEvents } from '@/lib/navigation-related-events' import { toNote } from '@/lib/link' import { cn } from '@/lib/utils' import { @@ -311,7 +312,7 @@ export default function Note({ } e.stopPropagation() client.addEventToCache(event) - navigateToNote(toNote(event), event) + navigateToNote(toNote(event), event, getCachedThreadContextEvents(event)) }} >
@@ -422,7 +423,7 @@ export default function Note({ onClick={(e) => { e.stopPropagation() client.addEventToCache(event) - navigateToNote(toNote(event), event) + navigateToNote(toNote(event), event, getCachedThreadContextEvents(event)) }} title="View in Discussions" > @@ -467,7 +468,12 @@ export default function Note({ className="mt-2" onClick={(e) => { e.stopPropagation() - navigateToNote(toNote(parentEventId)) + const parentEv = client.peekSessionCachedEvent(parentEventId) + navigateToNote( + toNote(parentEventId), + parentEv, + parentEv ? getCachedThreadContextEvents(parentEv) : undefined + ) }} /> ) : null} diff --git a/src/components/NoteCard/MainNoteCard.tsx b/src/components/NoteCard/MainNoteCard.tsx index 2cdfcc7b..8159737f 100644 --- a/src/components/NoteCard/MainNoteCard.tsx +++ b/src/components/NoteCard/MainNoteCard.tsx @@ -1,5 +1,6 @@ import { ExtendedKind } from '@/constants' import { Separator } from '@/components/ui/separator' +import { getCachedThreadContextEvents } from '@/lib/navigation-related-events' import { toNote } from '@/lib/link' import { useSmartNoteNavigationOptional } from '@/PageManager' import client from '@/services/client.service' @@ -67,7 +68,7 @@ export default function MainNoteCard({ e.stopPropagation() client.addEventToCache(event) const noteUrl = toNote(originalNoteId ?? event) - navigateToNote(noteUrl, event) + navigateToNote(noteUrl, event, getCachedThreadContextEvents(event)) }} >
diff --git a/src/components/ParentNotePreview/index.tsx b/src/components/ParentNotePreview/index.tsx index 3bfa8ed5..7ddc54e9 100644 --- a/src/components/ParentNotePreview/index.tsx +++ b/src/components/ParentNotePreview/index.tsx @@ -34,6 +34,7 @@ export default function ParentNotePreview({ try { const foundEvent = await client.fetchEventWithExternalRelays(eventId, SEARCHABLE_RELAY_URLS) if (foundEvent) { + client.addEventToCache(foundEvent) setFallbackEvent(foundEvent) } } catch (error) { diff --git a/src/components/ReplyNote/index.tsx b/src/components/ReplyNote/index.tsx index 08f3952a..ac3d961a 100644 --- a/src/components/ReplyNote/index.tsx +++ b/src/components/ReplyNote/index.tsx @@ -1,3 +1,4 @@ +import { getCachedThreadContextEvents } from '@/lib/navigation-related-events' import { useSmartNoteNavigation } from '@/PageManager' import { ExtendedKind } from '@/constants' import { Button } from '@/components/ui/button' @@ -94,7 +95,7 @@ export default function ReplyNote({ if (onClickReply) { onClickReply(event) } else { - navigateToNote(toNote(event), event) + navigateToNote(toNote(event), event, getCachedThreadContextEvents(event)) } }} > diff --git a/src/components/ReplyNoteList/index.tsx b/src/components/ReplyNoteList/index.tsx index 3c0d7d10..eaa0b8fd 100644 --- a/src/components/ReplyNoteList/index.tsx +++ b/src/components/ReplyNoteList/index.tsx @@ -21,6 +21,7 @@ import logger from '@/lib/logger' import { getZapInfoFromEvent } from '@/lib/event-metadata' import { normalizeUrl } from '@/lib/url' import { shouldHideThreadResponseEvent } from '@/lib/thread-response-filter' +import { getCachedThreadContextEvents } from '@/lib/navigation-related-events' import { toNote } from '@/lib/link' import { generateBech32IdFromETag } from '@/lib/tag' import { useSmartNoteNavigation, useSecondaryPage } from '@/PageManager' @@ -1079,7 +1080,16 @@ function ReplyNoteList({ onClickParent={() => { if (!parentEventHexId) return if (replies.every((r) => r.id !== parentEventHexId)) { - navigateToNote(toNote(parentEventId ?? parentEventHexId)) + const pid = parentEventId ?? parentEventHexId + const parentEv = + event.id.toLowerCase() === parentEventHexId.toLowerCase() + ? event + : client.peekSessionCachedEvent(pid) + navigateToNote( + toNote(pid), + parentEv ?? undefined, + parentEv ? getCachedThreadContextEvents(parentEv) : undefined + ) return } highlightReply(parentEventHexId) diff --git a/src/lib/navigation-related-events.ts b/src/lib/navigation-related-events.ts new file mode 100644 index 00000000..1b052fb7 --- /dev/null +++ b/src/lib/navigation-related-events.ts @@ -0,0 +1,20 @@ +import { getParentBech32Id, getRootBech32Id } from '@/lib/event' +import client from '@/services/client.service' +import type { Event } from 'nostr-tools' + +/** + * Parent / root events already in the session cache (e.g. from {@link ParentNotePreview} or the feed). + * Passed into {@link navigateToNote} as `relatedEvents` so {@link NotePage} can render the thread strip + * without a refetch — especially when the side panel mounts without `initialEvent`. + */ +export function getCachedThreadContextEvents(forEvent: Event): Event[] { + const byId = new Map() + const tryAdd = (bech32OrHex?: string) => { + if (!bech32OrHex?.trim()) return + const ev = client.peekSessionCachedEvent(bech32OrHex.trim()) + if (ev) byId.set(ev.id.toLowerCase(), ev) + } + tryAdd(getParentBech32Id(forEvent)) + tryAdd(getRootBech32Id(forEvent)) + return [...byId.values()] +} diff --git a/src/services/client-events.service.ts b/src/services/client-events.service.ts index 348b2804..00fac3fd 100644 --- a/src/services/client-events.service.ts +++ b/src/services/client-events.service.ts @@ -113,6 +113,16 @@ export class EventService { } } + /** + * Read parent/root (or any) event from the session cache without removing it. + * Accepts hex, note1, or nevent1 (not naddr). + */ + peekSessionCachedEvent(noteId: string): NEvent | undefined { + const hex = this.resolveHexWaiterKey(noteId.trim()) + if (!hex) return undefined + return this.getSessionEventIfAllowed(hex) + } + /** * When an event with this id is added to the session cache, invoke `callback` (and when already cached). * Only supports hex, note1, and nevent1 (not naddr). diff --git a/src/services/client.service.ts b/src/services/client.service.ts index 210305c9..2ece3dc6 100644 --- a/src/services/client.service.ts +++ b/src/services/client.service.ts @@ -2320,6 +2320,10 @@ class ClientService extends EventTarget { this.eventService.addEventToCache(event) } + peekSessionCachedEvent(noteId: string): NEvent | undefined { + return this.eventService.peekSessionCachedEvent(noteId) + } + getSessionEventsMatchingSearch(query: string, limit: number, allowedKinds: number[]): NEvent[] { return this.eventService.getSessionEventsMatchingSearch(query, limit, allowedKinds) }