diff --git a/packages/app/src/Element/Feed/Generic.tsx b/packages/app/src/Element/Feed/Generic.tsx new file mode 100644 index 000000000..f9b78428d --- /dev/null +++ b/packages/app/src/Element/Feed/Generic.tsx @@ -0,0 +1,32 @@ +import { NostrLink, NoteCollection, ReqFilter, RequestBuilder } from "@snort/system"; +import { useReactions, useRequestBuilder } from "@snort/system-react"; +import { useMemo } from "react"; +import { TimelineRenderer } from "./TimelineFragment"; + +export function GenericFeed({ link }: { link: NostrLink }) { + const sub = useMemo(() => { + console.debug(link); + const sub = new RequestBuilder("generic"); + sub.withOptions({ leaveOpen: true }); + const reqs = JSON.parse(link.id) as Array; + reqs.forEach(a => { + const f = sub.withBareFilter(a); + link.relays?.forEach(r => f.relay(r)); + }); + return sub; + }, [link]); + + const evs = useRequestBuilder(NoteCollection, sub); + const reactions = useReactions("generic:reactions", evs.data?.map(a => NostrLink.fromEvent(a)) ?? []); + + return ( + { + //nothing + }} + /> + ); +} diff --git a/packages/app/src/Pages/NostrLinkHandler.tsx b/packages/app/src/Pages/NostrLinkHandler.tsx index d3cb3e434..2f81e7cfa 100644 --- a/packages/app/src/Pages/NostrLinkHandler.tsx +++ b/packages/app/src/Pages/NostrLinkHandler.tsx @@ -7,6 +7,7 @@ import { fetchNip05Pubkey } from "@snort/shared"; import Spinner from "Icons/Spinner"; import ProfilePage from "Pages/Profile/ProfilePage"; import { ThreadRoute } from "Element/Event/Thread"; +import { GenericFeed } from "Element/Feed/Generic"; export default function NostrLinkHandler() { const params = useParams(); @@ -24,6 +25,8 @@ export default function NostrLinkHandler() { } else if (nav.type === NostrPrefix.PublicKey || nav.type === NostrPrefix.Profile) { const id = nav.encode(); setRenderComponent(); // Directly render ProfilePage + } else if (nav.type === NostrPrefix.Req) { + setRenderComponent(); } } else { if (state) { diff --git a/packages/app/src/index.tsx b/packages/app/src/index.tsx index 297c98ba2..a6a4be73e 100644 --- a/packages/app/src/index.tsx +++ b/packages/app/src/index.tsx @@ -18,6 +18,7 @@ import { NostrEvent, mapEventToProfile, PowWorker, + encodeTLVEntries, } from "@snort/system"; import { SnortContext } from "@snort/system-react"; import { removeUndefined, throwIfOffline } from "@snort/shared"; @@ -286,3 +287,7 @@ root.render( , ); + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +//@ts-ignore +window.encodeTLV = encodeTLVEntries; diff --git a/packages/system/src/links.ts b/packages/system/src/links.ts index 5d8bd3668..69a50a8d4 100644 --- a/packages/system/src/links.ts +++ b/packages/system/src/links.ts @@ -12,6 +12,7 @@ export const enum NostrPrefix { Event = "nevent", Relay = "nrelay", Address = "naddr", + Req = "nreq", } export enum TLVEntryType { @@ -54,7 +55,9 @@ export function encodeTLVEntries(prefix: NostrPrefix, ...entries: Array { return entity.startsWith(prefix); @@ -251,7 +251,12 @@ export function parseNostrLink(link: string, prefixHint?: NostrPrefix): NostrLin const id = bech32ToHex(entity); if (id.length !== 64) throw new Error("Invalid nostr link, must contain 32 byte id"); return new NostrLink(NostrPrefix.Note, id); - } else if (isPrefix(NostrPrefix.Profile) || isPrefix(NostrPrefix.Event) || isPrefix(NostrPrefix.Address)) { + } else if ( + isPrefix(NostrPrefix.Profile) || + isPrefix(NostrPrefix.Event) || + isPrefix(NostrPrefix.Address) || + isPrefix(NostrPrefix.Req) + ) { const decoded = decodeTLV(entity); const id = decoded.find(a => a.type === TLVEntryType.Special)?.value as string; @@ -267,6 +272,8 @@ export function parseNostrLink(link: string, prefixHint?: NostrPrefix): NostrLin return new NostrLink(NostrPrefix.Event, id, kind, author, relays); } else if (isPrefix(NostrPrefix.Address)) { return new NostrLink(NostrPrefix.Address, id, kind, author, relays); + } else if (isPrefix(NostrPrefix.Req)) { + return new NostrLink(NostrPrefix.Req, id); } } else if (prefixHint) { return new NostrLink(prefixHint, link);