Fix broken note links (#380)

* fix broken note links

* remove unused prop

* make comment easier to understand

* handle case where root event ID is missing

* add missing return

* fix root finding logic

* update comment
This commit is contained in:
Sam Samskies 2023-03-04 11:41:29 -10:00 committed by GitHub
parent 7928670153
commit 0a5491eede
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 7 deletions

View File

@ -1,6 +1,6 @@
import "./Text.css";
import { useMemo, useCallback } from "react";
import { Link } from "react-router-dom";
import { Link, useLocation } from "react-router-dom";
import ReactMarkdown from "react-markdown";
import { visit, SKIP } from "unist-util-visit";
import * as unist from "unist";
@ -28,6 +28,8 @@ export interface TextProps {
}
export default function Text({ content, tags, creator }: TextProps) {
const location = useLocation();
function extractLinks(fragments: Fragment[]) {
return fragments
.map(f => {
@ -80,7 +82,10 @@ export default function Text({ content, tags, creator }: TextProps) {
case "e": {
const eText = hexToBech32("note", ref.Event).substring(0, 12);
return (
<Link to={eventLink(ref.Event ?? "")} onClick={e => e.stopPropagation()}>
<Link
to={eventLink(ref.Event ?? "")}
onClick={e => e.stopPropagation()}
state={{ from: location.pathname }}>
#{eText}
</Link>
);

View File

@ -254,15 +254,12 @@ const TierThree = ({ active, path, isLastSubthread, from, notes, related, chains
};
export interface ThreadProps {
this?: u256;
notes?: TaggedRawEvent[];
}
export default function Thread(props: ThreadProps) {
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 [path, setPath] = useState<HexKey[]>([]);
const currentId = path.length > 0 && path[path.length - 1];
const currentRoot = useMemo(() => parsedNotes.find(a => a.Id === currentId), [notes, currentId]);
@ -295,6 +292,33 @@ export default function Thread(props: ThreadProps) {
return chains;
}, [notes]);
const root = useMemo(() => {
const isRoot = (ne?: NEvent) => ne?.Thread === null;
const currentNote = parsedNotes.find(ne => ne.Id === urlNoteHex);
if (isRoot(currentNote)) {
return currentNote;
}
const rootEventId = currentNote?.Thread?.Root?.Event;
// sometimes the root event ID is missing, and we can only take the happy path if the root event ID exists
if (rootEventId) {
return parsedNotes.find(ne => ne.Id === rootEventId);
}
const possibleRoots = parsedNotes.filter(isRoot);
// worst case we need to check every possible root to see which one contains the current note as a child
for (const ne of possibleRoots) {
const children = chains.get(ne.Id) ?? [];
if (children.find(ne => ne.Id === urlNoteHex)) {
return ne;
}
}
}, [notes, chains, urlNoteHex]);
useEffect(() => {
if (!root) {
return;
@ -370,7 +394,7 @@ export default function Thread(props: ThreadProps) {
const newPath = path.slice(0, path.length - 1);
setPath(newPath);
} else {
navigate("/");
navigate(location.state?.from ?? "/");
}
}

View File

@ -8,5 +8,5 @@ export default function EventPage() {
const id = parseId(params.id ?? "");
const thread = useThreadFeed(id);
return <Thread notes={thread.notes} this={id} />;
return <Thread key={id} notes={thread.notes} />;
}