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:
parent
7928670153
commit
0a5491eede
@ -1,6 +1,6 @@
|
|||||||
import "./Text.css";
|
import "./Text.css";
|
||||||
import { useMemo, useCallback } from "react";
|
import { useMemo, useCallback } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link, useLocation } from "react-router-dom";
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
import { visit, SKIP } from "unist-util-visit";
|
import { visit, SKIP } from "unist-util-visit";
|
||||||
import * as unist from "unist";
|
import * as unist from "unist";
|
||||||
@ -28,6 +28,8 @@ export interface TextProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function Text({ content, tags, creator }: TextProps) {
|
export default function Text({ content, tags, creator }: TextProps) {
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
function extractLinks(fragments: Fragment[]) {
|
function extractLinks(fragments: Fragment[]) {
|
||||||
return fragments
|
return fragments
|
||||||
.map(f => {
|
.map(f => {
|
||||||
@ -80,7 +82,10 @@ export default function Text({ content, tags, creator }: TextProps) {
|
|||||||
case "e": {
|
case "e": {
|
||||||
const eText = hexToBech32("note", ref.Event).substring(0, 12);
|
const eText = hexToBech32("note", ref.Event).substring(0, 12);
|
||||||
return (
|
return (
|
||||||
<Link to={eventLink(ref.Event ?? "")} onClick={e => e.stopPropagation()}>
|
<Link
|
||||||
|
to={eventLink(ref.Event ?? "")}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
state={{ from: location.pathname }}>
|
||||||
#{eText}
|
#{eText}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
@ -254,15 +254,12 @@ const TierThree = ({ active, path, isLastSubthread, from, notes, related, chains
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface ThreadProps {
|
export interface ThreadProps {
|
||||||
this?: u256;
|
|
||||||
notes?: TaggedRawEvent[];
|
notes?: TaggedRawEvent[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Thread(props: ThreadProps) {
|
export default function Thread(props: ThreadProps) {
|
||||||
const notes = props.notes ?? [];
|
const notes = props.notes ?? [];
|
||||||
const parsedNotes = notes.map(a => new NEvent(a));
|
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 [path, setPath] = useState<HexKey[]>([]);
|
||||||
const currentId = path.length > 0 && path[path.length - 1];
|
const currentId = path.length > 0 && path[path.length - 1];
|
||||||
const currentRoot = useMemo(() => parsedNotes.find(a => a.Id === currentId), [notes, currentId]);
|
const currentRoot = useMemo(() => parsedNotes.find(a => a.Id === currentId), [notes, currentId]);
|
||||||
@ -295,6 +292,33 @@ export default function Thread(props: ThreadProps) {
|
|||||||
return chains;
|
return chains;
|
||||||
}, [notes]);
|
}, [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(() => {
|
useEffect(() => {
|
||||||
if (!root) {
|
if (!root) {
|
||||||
return;
|
return;
|
||||||
@ -370,7 +394,7 @@ export default function Thread(props: ThreadProps) {
|
|||||||
const newPath = path.slice(0, path.length - 1);
|
const newPath = path.slice(0, path.length - 1);
|
||||||
setPath(newPath);
|
setPath(newPath);
|
||||||
} else {
|
} else {
|
||||||
navigate("/");
|
navigate(location.state?.from ?? "/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,5 +8,5 @@ export default function EventPage() {
|
|||||||
const id = parseId(params.id ?? "");
|
const id = parseId(params.id ?? "");
|
||||||
const thread = useThreadFeed(id);
|
const thread = useThreadFeed(id);
|
||||||
|
|
||||||
return <Thread notes={thread.notes} this={id} />;
|
return <Thread key={id} notes={thread.notes} />;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user