Browse Source

pass reply-to event when opening the side-panel

imwald
Silberengel 1 month ago
parent
commit
1b5d861349
  1. 3
      src/components/Embedded/EmbeddedNote.tsx
  2. 12
      src/components/Note/index.tsx
  3. 3
      src/components/NoteCard/MainNoteCard.tsx
  4. 1
      src/components/ParentNotePreview/index.tsx
  5. 3
      src/components/ReplyNote/index.tsx
  6. 12
      src/components/ReplyNoteList/index.tsx
  7. 20
      src/lib/navigation-related-events.ts
  8. 10
      src/services/client-events.service.ts
  9. 4
      src/services/client.service.ts

3
src/components/Embedded/EmbeddedNote.tsx

@ -19,6 +19,7 @@ import logger from '@/lib/logger'
import { extractBookMetadata } from '@/lib/bookstr-parser' import { extractBookMetadata } from '@/lib/bookstr-parser'
import { contentParserService } from '@/services/content-parser.service' import { contentParserService } from '@/services/content-parser.service'
import { useSmartNoteNavigationOptional } from '@/PageManager' import { useSmartNoteNavigationOptional } from '@/PageManager'
import { getCachedThreadContextEvents } from '@/lib/navigation-related-events'
import { toNote } from '@/lib/link' import { toNote } from '@/lib/link'
import { import {
type EmbeddedNoteIdValidation, type EmbeddedNoteIdValidation,
@ -597,7 +598,7 @@ function EmbeddedBookstrEvent({ event, originalNoteId, className }: { event: Eve
} }
e.stopPropagation() e.stopPropagation()
const noteUrl = toNote(originalNoteId ?? event) const noteUrl = toNote(originalNoteId ?? event)
navigateToNote(noteUrl, event) navigateToNote(noteUrl, event, getCachedThreadContextEvents(event))
}} }}
> >
{/* Header */} {/* Header */}

12
src/components/Note/index.tsx

@ -8,6 +8,7 @@ import {
isNip25ReactionKind, isNip25ReactionKind,
isNsfwEvent isNsfwEvent
} from '@/lib/event' } from '@/lib/event'
import { getCachedThreadContextEvents } from '@/lib/navigation-related-events'
import { toNote } from '@/lib/link' import { toNote } from '@/lib/link'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { import {
@ -311,7 +312,7 @@ export default function Note({
} }
e.stopPropagation() e.stopPropagation()
client.addEventToCache(event) client.addEventToCache(event)
navigateToNote(toNote(event), event) navigateToNote(toNote(event), event, getCachedThreadContextEvents(event))
}} }}
> >
<div className="flex justify-between items-start gap-2"> <div className="flex justify-between items-start gap-2">
@ -422,7 +423,7 @@ export default function Note({
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
client.addEventToCache(event) client.addEventToCache(event)
navigateToNote(toNote(event), event) navigateToNote(toNote(event), event, getCachedThreadContextEvents(event))
}} }}
title="View in Discussions" title="View in Discussions"
> >
@ -467,7 +468,12 @@ export default function Note({
className="mt-2" className="mt-2"
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
navigateToNote(toNote(parentEventId)) const parentEv = client.peekSessionCachedEvent(parentEventId)
navigateToNote(
toNote(parentEventId),
parentEv,
parentEv ? getCachedThreadContextEvents(parentEv) : undefined
)
}} }}
/> />
) : null} ) : null}

3
src/components/NoteCard/MainNoteCard.tsx

@ -1,5 +1,6 @@
import { ExtendedKind } from '@/constants' import { ExtendedKind } from '@/constants'
import { Separator } from '@/components/ui/separator' import { Separator } from '@/components/ui/separator'
import { getCachedThreadContextEvents } from '@/lib/navigation-related-events'
import { toNote } from '@/lib/link' import { toNote } from '@/lib/link'
import { useSmartNoteNavigationOptional } from '@/PageManager' import { useSmartNoteNavigationOptional } from '@/PageManager'
import client from '@/services/client.service' import client from '@/services/client.service'
@ -67,7 +68,7 @@ export default function MainNoteCard({
e.stopPropagation() e.stopPropagation()
client.addEventToCache(event) client.addEventToCache(event)
const noteUrl = toNote(originalNoteId ?? event) const noteUrl = toNote(originalNoteId ?? event)
navigateToNote(noteUrl, event) navigateToNote(noteUrl, event, getCachedThreadContextEvents(event))
}} }}
> >
<div className={`clickable ${embedded ? 'p-2 sm:p-3 border rounded-lg' : 'py-3'}`} style={embedded ? { position: 'relative', isolation: 'isolate', overflow: 'visible' } : undefined}> <div className={`clickable ${embedded ? 'p-2 sm:p-3 border rounded-lg' : 'py-3'}`} style={embedded ? { position: 'relative', isolation: 'isolate', overflow: 'visible' } : undefined}>

1
src/components/ParentNotePreview/index.tsx

@ -34,6 +34,7 @@ export default function ParentNotePreview({
try { try {
const foundEvent = await client.fetchEventWithExternalRelays(eventId, SEARCHABLE_RELAY_URLS) const foundEvent = await client.fetchEventWithExternalRelays(eventId, SEARCHABLE_RELAY_URLS)
if (foundEvent) { if (foundEvent) {
client.addEventToCache(foundEvent)
setFallbackEvent(foundEvent) setFallbackEvent(foundEvent)
} }
} catch (error) { } catch (error) {

3
src/components/ReplyNote/index.tsx

@ -1,3 +1,4 @@
import { getCachedThreadContextEvents } from '@/lib/navigation-related-events'
import { useSmartNoteNavigation } from '@/PageManager' import { useSmartNoteNavigation } from '@/PageManager'
import { ExtendedKind } from '@/constants' import { ExtendedKind } from '@/constants'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
@ -94,7 +95,7 @@ export default function ReplyNote({
if (onClickReply) { if (onClickReply) {
onClickReply(event) onClickReply(event)
} else { } else {
navigateToNote(toNote(event), event) navigateToNote(toNote(event), event, getCachedThreadContextEvents(event))
} }
}} }}
> >

12
src/components/ReplyNoteList/index.tsx

@ -21,6 +21,7 @@ import logger from '@/lib/logger'
import { getZapInfoFromEvent } from '@/lib/event-metadata' import { getZapInfoFromEvent } from '@/lib/event-metadata'
import { normalizeUrl } from '@/lib/url' import { normalizeUrl } from '@/lib/url'
import { shouldHideThreadResponseEvent } from '@/lib/thread-response-filter' import { shouldHideThreadResponseEvent } from '@/lib/thread-response-filter'
import { getCachedThreadContextEvents } from '@/lib/navigation-related-events'
import { toNote } from '@/lib/link' import { toNote } from '@/lib/link'
import { generateBech32IdFromETag } from '@/lib/tag' import { generateBech32IdFromETag } from '@/lib/tag'
import { useSmartNoteNavigation, useSecondaryPage } from '@/PageManager' import { useSmartNoteNavigation, useSecondaryPage } from '@/PageManager'
@ -1079,7 +1080,16 @@ function ReplyNoteList({
onClickParent={() => { onClickParent={() => {
if (!parentEventHexId) return if (!parentEventHexId) return
if (replies.every((r) => r.id !== parentEventHexId)) { 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 return
} }
highlightReply(parentEventHexId) highlightReply(parentEventHexId)

20
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<string, Event>()
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()]
}

10
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). * 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). * Only supports hex, note1, and nevent1 (not naddr).

4
src/services/client.service.ts

@ -2320,6 +2320,10 @@ class ClientService extends EventTarget {
this.eventService.addEventToCache(event) this.eventService.addEventToCache(event)
} }
peekSessionCachedEvent(noteId: string): NEvent | undefined {
return this.eventService.peekSessionCachedEvent(noteId)
}
getSessionEventsMatchingSearch(query: string, limit: number, allowedKinds: number[]): NEvent[] { getSessionEventsMatchingSearch(query: string, limit: number, allowedKinds: number[]): NEvent[] {
return this.eventService.getSessionEventsMatchingSearch(query, limit, allowedKinds) return this.eventService.getSessionEventsMatchingSearch(query, limit, allowedKinds)
} }

Loading…
Cancel
Save