feat: render note quotes

This commit is contained in:
Kieran 2023-04-18 22:20:13 +01:00
parent a6eefb1027
commit 13461cca80
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
11 changed files with 61 additions and 25 deletions

View File

@ -26,7 +26,7 @@ import NostrLink from "Element/NostrLink";
import RevealMedia from "Element/RevealMedia";
import MagnetLink from "Element/MagnetLink";
export default function HyperText({ link, creator }: { link: string; creator: string }) {
export default function HyperText({ link, creator, depth }: { link: string; creator: string; depth?: number }) {
const a = link;
try {
const url = new URL(a);
@ -85,7 +85,7 @@ export default function HyperText({ link, creator }: { link: string; creator: st
} else if (isWavlakeLink) {
return <WavlakeEmbed link={a} />;
} else if (url.protocol === "nostr:" || url.protocol === "web+nostr:") {
return <NostrLink link={a} />;
return <NostrLink link={a} depth={depth} />;
} else if (url.protocol === "magnet:") {
const parsed = magnetURIDecode(a);
if (parsed) {

View File

@ -2,23 +2,23 @@ import useEventFeed from "Feed/EventFeed";
import { NostrLink } from "Util";
import HyperText from "Element/HyperText";
import { FormattedMessage } from "react-intl";
import Spinner from "Icons/Spinner";
import PageSpinner from "Element/PageSpinner";
export default function NostrFileHeader({ link }: { link: NostrLink }) {
const ev = useEventFeed(link);
if (!ev.data?.length) return <Spinner />;
if (!ev.data) return <PageSpinner />;
// assume image or embed which can be rendered by the hypertext kind
// todo: make use of hash
// todo: use magnet or other links if present
const u = ev.data?.[0]?.tags.find(a => a[0] === "u")?.[1] ?? "";
const u = ev.data?.tags.find(a => a[0] === "u")?.[1] ?? "";
if (u) {
return <HyperText link={u} creator={ev.data?.[0]?.pubkey ?? ""} />;
return <HyperText link={u} creator={ev.data?.pubkey ?? ""} />;
} else {
return (
<b className="error">
<FormattedMessage defaultMessage="Unknown file header: {name}" values={{ name: ev.data?.[0]?.content }} />
<FormattedMessage defaultMessage="Unknown file header: {name}" values={{ name: ev.data?.content }} />
</b>
);
}

View File

@ -1,11 +1,12 @@
import { EventKind, NostrPrefix } from "@snort/nostr";
import { Link } from "react-router-dom";
import { EventKind, NostrPrefix } from "@snort/nostr";
import Mention from "Element/Mention";
import NostrFileHeader from "Element/NostrFileHeader";
import { parseNostrLink } from "Util";
import NoteQuote from "Element/NoteQuote";
export default function NostrLink({ link }: { link: string }) {
export default function NostrLink({ link, depth }: { link: string; depth?: number }) {
const nav = parseNostrLink(link);
if (nav?.type === NostrPrefix.PublicKey || nav?.type === NostrPrefix.Profile) {
@ -14,12 +15,16 @@ export default function NostrLink({ link }: { link: string }) {
if (nav.kind === EventKind.FileHeader) {
return <NostrFileHeader link={nav} />;
}
const evLink = nav.encode();
return (
<Link to={`/e/${evLink}`} onClick={e => e.stopPropagation()} state={{ from: location.pathname }}>
#{evLink.substring(0, 12)}
</Link>
);
if ((depth ?? 0) > 0) {
const evLink = nav.encode();
return (
<Link to={`/e/${evLink}`} onClick={e => e.stopPropagation()} state={{ from: location.pathname }}>
#{evLink.substring(0, 12)}
</Link>
);
} else {
return <NoteQuote link={nav} depth={depth} />;
}
} else {
return (
<a href={link} onClick={e => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">

View File

@ -57,6 +57,14 @@
margin-right: 8px;
}
.note-quote {
border: 1px solid var(--gray);
}
.note-quote.note > .body {
padding-left: 0;
}
.note > .body {
margin-top: 4px;
margin-bottom: 24px;
@ -98,9 +106,6 @@
border-radius: 16px;
}
.light .note > .footer .ctx-menu {
}
.note > .footer .ctx-menu li {
background: #1e1e1e;
padding-top: 8px;

View File

@ -39,6 +39,7 @@ export interface NoteProps {
highlight?: boolean;
ignoreModeration?: boolean;
onClick?: (e: TaggedRawEvent) => void;
depth?: number;
options?: {
showHeader?: boolean;
showTime?: boolean;
@ -187,7 +188,7 @@ export default function Note(props: NoteProps) {
</Reveal>
);
}
return <Text content={body} tags={ev.tags} creator={ev.pubkey} />;
return <Text content={body} tags={ev.tags} creator={ev.pubkey} depth={props.depth} />;
};
useLayoutEffect(() => {

View File

@ -0,0 +1,20 @@
import useEventFeed from "Feed/EventFeed";
import { NostrLink } from "Util";
import Note from "Element/Note";
import PageSpinner from "Element/PageSpinner";
export default function NoteQuote({ link, depth }: { link: NostrLink; depth?: number }) {
const ev = useEventFeed(link);
if (!ev.data) return <PageSpinner />;
return (
<Note
data={ev.data}
related={[]}
className="note-quote"
depth={(depth ?? 0) + 1}
options={{
showFooter: false,
}}
/>
);
}

View File

@ -5,7 +5,7 @@
word-break: break-word;
}
.text a {
.text > a {
color: var(--highlight);
text-decoration: none;
}

View File

@ -25,9 +25,10 @@ export interface TextProps {
creator: HexKey;
tags: Array<Array<string>>;
disableMedia?: boolean;
depth?: number;
}
export default function Text({ content, tags, creator, disableMedia }: TextProps) {
export default function Text({ content, tags, creator, disableMedia, depth }: TextProps) {
const location = useLocation();
function extractLinks(fragments: Fragment[]) {
@ -43,7 +44,7 @@ export default function Text({ content, tags, creator, disableMedia }: TextProps
</a>
);
}
return <HyperText link={a} creator={creator} />;
return <HyperText link={a} creator={creator} depth={depth} />;
}
return a;
});

View File

@ -88,7 +88,9 @@ const Timeline = (props: TimelineProps) => {
if (eRef) {
return <NoteReaction data={e} key={e.id} root={findRelated(eRef)} />;
}
return <Note key={e.id} data={e} related={relatedFeed(e.id)} ignoreModeration={props.ignoreModeration} />;
return (
<Note key={e.id} data={e} related={relatedFeed(e.id)} ignoreModeration={props.ignoreModeration} depth={0} />
);
}
case EventKind.ZapReceipt: {
const zap = parseZap(e);

View File

@ -1,7 +1,7 @@
import { useMemo } from "react";
import useRequestBuilder from "Hooks/useRequestBuilder";
import { FlatNoteStore, RequestBuilder } from "System";
import { RequestBuilder, ReplaceableNoteStore } from "System";
import { NostrLink } from "Util";
export default function useEventFeed(link: NostrLink) {
@ -11,5 +11,5 @@ export default function useEventFeed(link: NostrLink) {
return b;
}, [link]);
return useRequestBuilder<FlatNoteStore>(FlatNoteStore, sub);
return useRequestBuilder<ReplaceableNoteStore>(ReplaceableNoteStore, sub);
}

View File

@ -8,6 +8,7 @@ import {
NoteStore,
PubkeyReplaceableNoteStore,
ParameterizedReplaceableNoteStore,
ReplaceableNoteStore,
} from "./NoteCollection";
import { diffFilters } from "./RequestSplitter";
import { Query } from "./Query";
@ -18,6 +19,7 @@ export {
FlatNoteStore,
PubkeyReplaceableNoteStore,
ParameterizedReplaceableNoteStore,
ReplaceableNoteStore,
Query,
EventBuilder,
};