diff --git a/src/element/Note.css b/src/element/Note.css
index e7122ded..57ce054d 100644
--- a/src/element/Note.css
+++ b/src/element/Note.css
@@ -34,4 +34,9 @@
.note > .footer {
padding: 10px 0;
text-align: right;
+}
+
+.indented {
+ border-left: 3px solid #444;
+ padding-left: 2px;
}
\ No newline at end of file
diff --git a/src/element/Thread.js b/src/element/Thread.js
index 610743d1..91deeb98 100644
--- a/src/element/Thread.js
+++ b/src/element/Thread.js
@@ -1,3 +1,4 @@
+import { useMemo } from "react";
import Event from "../nostr/Event";
import EventKind from "../nostr/EventKind";
import Note from "./Note";
@@ -10,25 +11,63 @@ export default function Thread(props) {
const notes = props.notes?.map(a => Event.FromObject(a));
// root note has no thread info
- const root = notes.find(a => a.GetThread() === null);
+ const root = useMemo(() => notes.find(a => a.GetThread() === null), [notes]);
+
+ const chains = useMemo(() => {
+ let chains = new Map();
+ notes.filter(a => a.Kind === EventKind.TextNote).sort((a, b) => b.CreatedAt - a.CreatedAt).forEach((v) => {
+ let thread = v.GetThread();
+ let replyTo = thread?.ReplyTo?.Event ?? 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]);
function reactions(id, kind = EventKind.Reaction) {
return notes?.filter(a => a.Kind === kind && a.Tags.find(a => a.Key === "e" && a.Event === id));
}
- const repliesToRoot = notes?.
- filter(a => a.GetThread()?.Root !== null && a.Kind === EventKind.TextNote && a.Id !== thisEvent && a.Id !== root?.Id)
- .sort((a, b) => a.CreatedAt - b.CreatedAt);
- const thisNote = notes?.find(a => a.Id === thisEvent);
- const thisIsRootNote = thisNote?.Id === root?.Id;
+ function renderRoot() {
+ if (root) {
+ return