diff --git a/src/element/Note.js b/src/element/Note.js
index f191f75a..a2bc6b1e 100644
--- a/src/element/Note.js
+++ b/src/element/Note.js
@@ -1,10 +1,11 @@
import "./Note.css";
-import Event from "../nostr/Event";
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import moment from "moment";
import { Link, useNavigate } from "react-router-dom";
+import Event from "../nostr/Event";
import ProfileImage from "./ProfileImage";
+import useEventPublisher from "../pages/feed/EventPublisher";
const UrlRegex = /((?:http|ftp|https):\/\/(?:[\w+?\.\w+])+(?:[a-zA-Z0-9\~\!\@\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\.\:\;\'\,]*)?)/;
const FileExtensionRegex = /\.([\w]+)$/;
@@ -13,11 +14,12 @@ const MentionRegex = /(#\[\d+\])/g;
export default function Note(props) {
const navigate = useNavigate();
const data = props.data;
+ const dataEvent = props["data-ev"];
const reactions = props.reactions;
+ const publisher = useEventPublisher();
const [sig, setSig] = useState(false);
const users = useSelector(s => s.users?.users);
- const user = users[data?.pubkey];
- const ev = Event.FromObject(data);
+ const ev = dataEvent ?? Event.FromObject(data);
useEffect(() => {
if (sig === false) {
@@ -109,6 +111,11 @@ export default function Note(props) {
});
}
+ async function like() {
+ let evLike = await publisher.like(ev);
+ publisher.broadcast(evLike);
+ }
+
if (!ev.IsContent()) {
return (
<>
@@ -131,7 +138,7 @@ export default function Note(props) {
{transformBody()}
-
+ like()}>
👍 {(reactions?.length ?? 0)}
console.debug(ev)}>
diff --git a/src/element/NoteGhost.js b/src/element/NoteGhost.js
index 0452cb55..2a20a0f5 100644
--- a/src/element/NoteGhost.js
+++ b/src/element/NoteGhost.js
@@ -1,5 +1,4 @@
import "./Note.css";
-import moment from "moment";
import ProfileImage from "./ProfileImage";
export default function NoteGhost(props) {
@@ -7,12 +6,9 @@ export default function NoteGhost(props) {
-
- {moment().fromNow()}
-
- Loading...
+ {props.text ?? "Loading..."}
diff --git a/src/element/Thread.js b/src/element/Thread.js
index 4e0aaad7..5bc27830 100644
--- a/src/element/Thread.js
+++ b/src/element/Thread.js
@@ -4,6 +4,8 @@ import Note from "./Note";
import NoteGhost from "./NoteGhost";
export default function Thread(props) {
+ const thisEvent = props.this;
+
/** @type {Array
} */
const notes = props.notes?.map(a => Event.FromObject(a));
@@ -11,18 +13,21 @@ export default function Thread(props) {
const root = notes.find(a => a.GetThread() === null);
function reactions(id) {
- return notes?.filter(a => a.Kind === EventKind.Reaction && a.GetThread()?.Root?.Event === id);
+ return notes?.filter(a => a.Kind === EventKind.Reaction && a.Tags.find(a => a.Key === "e").Event === id);
}
const repliesToRoot = notes?.
- filter(a => a.GetThread()?.Root?.Event === root?.Id && a.Kind === EventKind.TextNote)
- .sort((a, b) => b.CreatedAt - a.CreatedAt);
+ filter(a => a.GetThread()?.Root !== null && a.Kind === EventKind.TextNote && a.Id !== thisEvent)
+ .sort((a, b) => a.CreatedAt - b.CreatedAt);
+ const thisNote = notes?.find(a => a.Id === thisEvent);
return (
<>
{root === undefined ?
-
- : }
- {repliesToRoot?.map(a => )}
+
+ : }
+ {thisNote ? : null}
+ Other Replies
+ {repliesToRoot?.map(a => )}
>
);
}
\ No newline at end of file
diff --git a/src/nostr/Event.js b/src/nostr/Event.js
index 2b32954b..a92b9b0f 100644
--- a/src/nostr/Event.js
+++ b/src/nostr/Event.js
@@ -149,30 +149,4 @@ export default class Event {
ev.PubKey = pubKey;
return ev;
}
-
- /**
- * Create new SetMetadata event
- * @param {String} pubKey Pubkey of the creator of this event
- * @param {any} obj Metadata content
- * @returns {Event}
- */
- static SetMetadata(pubKey, obj) {
- let ev = Event.ForPubKey(pubKey);
- ev.Kind = EventKind.SetMetadata;
- ev.Content = JSON.stringify(obj);
- return ev;
- }
-
- /**
- * Create a new TextNote event
- * @param {String} pubKey
- * @param {String} message
- * @returns
- */
- static NewNote(pubKey, message) {
- let ev = Event.ForPubKey(pubKey);
- ev.Kind = EventKind.TextNote;
- ev.Content = message;
- return ev;
- }
}
\ No newline at end of file
diff --git a/src/pages/EventPage.js b/src/pages/EventPage.js
index 002ae9bb..ab27f395 100644
--- a/src/pages/EventPage.js
+++ b/src/pages/EventPage.js
@@ -7,5 +7,5 @@ export default function EventPage() {
const id = params.id;
const { notes } = useThreadFeed(id);
- return ;
+ return ;
}
\ No newline at end of file
diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js
index 8deabd70..37f9a9ba 100644
--- a/src/pages/ProfilePage.js
+++ b/src/pages/ProfilePage.js
@@ -3,19 +3,17 @@ import { useDispatch, useSelector } from "react-redux";
import { useParams } from "react-router-dom";
import useProfile from "./feed/ProfileFeed";
import { useContext, useEffect, useState } from "react";
-import Event from "../nostr/Event";
-import { NostrContext } from "..";
import { resetProfile } from "../state/Users";
import Nostrich from "../nostrich.jpg";
+import useEventPublisher from "./feed/EventPublisher";
export default function ProfilePage() {
- const system = useContext(NostrContext);
const dispatch = useDispatch();
const params = useParams();
const id = params.id;
const user = useProfile(id);
+ const publisher = useEventPublisher();
const loginPubKey = useSelector(s => s.login.publicKey);
- const privKey = useSelector(s => s.login.privateKey);
const isMe = loginPubKey === id;
let [name, setName] = useState("");
@@ -37,7 +35,7 @@ export default function ProfilePage() {
}, [user]);
async function saveProfile() {
- let ev = Event.SetMetadata(id, {
+ let ev = await publisher.metadata({
name,
about,
picture,
@@ -45,10 +43,8 @@ export default function ProfilePage() {
nip05,
lud16
});
- await ev.Sign(privKey);
-
console.debug(ev);
- system.BroadcastEvent(ev);
+ publisher.broadcast(ev);
dispatch(resetProfile(id));
}
diff --git a/src/pages/Root.js b/src/pages/Root.js
index d3caa240..6859be34 100644
--- a/src/pages/Root.js
+++ b/src/pages/Root.js
@@ -1,22 +1,20 @@
import "./Root.css";
-import Timeline from "./Timeline";
import { useSelector } from "react-redux";
-import { useContext, useState } from "react";
-import Event from "../nostr/Event";
-import { NostrContext } from "..";
+import { useState } from "react";
+import Timeline from "./Timeline";
+import useEventPublisher from "./feed/EventPublisher";
export default function RootPage() {
- const system = useContext(NostrContext);
+ const publisher = useEventPublisher();
const pubKey = useSelector(s => s.login.publicKey);
- const privKey = useSelector(s => s.login.privateKey);
+
const [note, setNote] = useState("");
async function sendNote() {
- let ev = Event.NewNote(pubKey, note);
- await ev.Sign(privKey);
+ let ev = await publisher.note(note);
console.debug("Sending note: ", ev);
- system.BroadcastEvent(ev);
+ publisher.broadcast(ev);
setNote("");
}
diff --git a/src/pages/feed/EventPublisher.js b/src/pages/feed/EventPublisher.js
new file mode 100644
index 00000000..712e5868
--- /dev/null
+++ b/src/pages/feed/EventPublisher.js
@@ -0,0 +1,54 @@
+import { useContext } from "react";
+import { useSelector } from "react-redux";
+import { NostrContext } from "../..";
+import Event from "../../nostr/Event";
+import EventKind from "../../nostr/EventKind";
+import Tag from "../../nostr/Tag";
+
+export default function useEventPublisher() {
+ const system = useContext(NostrContext);
+ const pubKey = useSelector(s => s.login.publicKey);
+ const privKey = useSelector(s => s.login.privateKey);
+
+ return {
+ broadcast: (ev) => {
+ console.debug("Sending event: ", ev);
+ system.BroadcastEvent(ev);
+ },
+ metadata: async (obj) => {
+ let ev = Event.ForPubKey(pubKey);
+ ev.Kind = EventKind.SetMetadata;
+ ev.Content = JSON.stringify(obj);
+ await ev.Sign(privKey);
+ return ev;
+ },
+ note: async (msg) => {
+ if(typeof msg !== "string") {
+ throw "Must be text!";
+ }
+ let ev = Event.ForPubKey(pubKey);
+ ev.Kind = EventKind.TextNote;
+ ev.Content = msg;
+ await ev.Sign(privKey);
+ return ev;
+ },
+ like: async (evRef) => {
+ let ev = Event.ForPubKey(pubKey);
+ ev.Kind = EventKind.Reaction;
+ ev.Content = "+";
+ ev.Tags.push(new Tag(["e", evRef.Id], 0));
+ ev.Tags.push(new Tag(["p", evRef.PubKey], 1));
+ await ev.Sign(privKey);
+ return ev;
+ },
+ dislike: async (evRef) => {
+ let ev = Event.ForPubKey(pubKey);
+ ev.Kind = EventKind.Reaction;
+ ev.Content = "-";
+ ev.Tags.push(new Tag(["e", evRef.Id], 0));
+ ev.Tags.push(new Tag(["p", evRef.PubKey], 1));
+ await ev.Sign(privKey);
+ return ev;
+ }
+ }
+}
\ No newline at end of file