import { useMemo } from "react"; import { Link } from "react-router-dom"; import { TaggedRawEvent, u256 } from "../nostr"; import { default as NEvent } from "../nostr/Event"; import EventKind from "../nostr/EventKind"; import { eventLink } from "../Util"; import Note from "./Note"; import NoteGhost from "./NoteGhost"; export interface ThreadProps { this?: u256, notes?: TaggedRawEvent[] } export default function Thread(props: ThreadProps) { const thisEvent = props.this; const notes = props.notes ?? []; const parsedNotes = notes.map(a => new NEvent(a)); // root note has no thread info const root = useMemo(() => parsedNotes.find(a => a.Thread === null), [notes]); const chains = useMemo(() => { let chains = new Map(); parsedNotes?.filter(a => a.Kind === EventKind.TextNote).sort((a, b) => b.CreatedAt - a.CreatedAt).forEach((v) => { let replyTo = v.Thread?.ReplyTo?.Event ?? v.Thread?.Root?.Event; if (replyTo) { if (!chains.has(replyTo)) { chains.set(replyTo, [v]); } else { chains.get(replyTo)!.push(v); } } else if (v.Tags.length > 0) { console.log("Not replying to anything: ", v); } }); return chains; }, [notes]); const brokenChains = useMemo(() => { return Array.from(chains?.keys()).filter(a => !parsedNotes?.some(b => b.Id === a)); }, [chains]); const mentionsRoot = useMemo(() => { return parsedNotes?.filter(a => a.Kind === EventKind.TextNote && a.Thread) }, [chains]); function renderRoot() { if (root) { return } else { return Loading thread root.. ({notes?.length} notes loaded) } } function renderChain(from: u256) { if (from && chains) { let replies = chains.get(from); if (replies) { return (
{replies.map(a => { return ( <> {renderChain(a.Id)} ) })}
) } } } return ( <> {renderRoot()} {root ? renderChain(root.Id) : null} {root ? null : <>

Other Replies

{brokenChains.map(a => { return ( <> Missing event {a.substring(0, 8)} {renderChain(a)} ) })} } ); }