diff --git a/src/element/Note.js b/src/element/Note.js index a25fe045..b797823f 100644 --- a/src/element/Note.js +++ b/src/element/Note.js @@ -3,7 +3,7 @@ import { useCallback, useState } from "react"; import { useSelector } from "react-redux"; import moment from "moment"; import { Link, useNavigate } from "react-router-dom"; -import { faHeart, faReply, faInfo, faTrash } from "@fortawesome/free-solid-svg-icons"; +import { faHeart, faThumbsDown, faReply, faInfo, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import Event from "../nostr/Event"; @@ -20,12 +20,21 @@ export default function Note(props) { const dataEvent = props["data-ev"]; const reactions = props.reactions; const deletion = props.deletion; + const emojiReactions = reactions?.filter(({ Content }) => Content && Content !== "+" && Content !== "-" && Content !== "❤️") + .reduce((acc, { Content }) => { + const amount = acc[Content] || 0 + return {...acc, [Content]: amount + 1 } + }, {}) + const likes = reactions?.filter(({ Content }) => Content === "+" || Content === "❤️").length ?? 0 + const dislikes = reactions?.filter(({ Content }) => Content === "-").length ?? 0 const publisher = useEventPublisher(); const [showReply, setShowReply] = useState(false); const users = useSelector(s => s.users?.users); const login = useSelector(s => s.login.publicKey); const ev = dataEvent ?? Event.FromObject(data); const isMine = ev.PubKey === login; + const liked = reactions?.find(({ PubKey, Content }) => Content === "+" && PubKey === login) + const disliked = reactions?.find(({ PubKey, Content }) => Content === "-" && PubKey === login) const options = { showHeader: true, @@ -34,6 +43,10 @@ export default function Note(props) { ...opt }; + function hasReacted(emoji) { + return reactions?.find(({ PubKey, Content }) => Content === emoji && PubKey === login) + } + const transformBody = useCallback(() => { let body = ev?.Content ?? ""; @@ -71,11 +84,21 @@ export default function Note(props) { ) } + async function react(emoji) { + let evLike = await publisher.like(ev, emoji); + publisher.broadcast(evLike); + } + async function like() { let evLike = await publisher.like(ev); publisher.broadcast(evLike); } + async function dislike() { + let evLike = await publisher.dislike(ev); + publisher.broadcast(evLike); + } + async function deleteEvent() { if (window.confirm(`Are you sure you want to delete ${ev.Id.substring(0, 8)}?`)) { let evDelete = await publisher.delete(ev.Id); @@ -114,9 +137,24 @@ export default function Note(props) { setShowReply(!showReply)}> + {Object.keys(emojiReactions).map((emoji) => { + return ( + react(emoji)}> + + {emoji} + +   + {emojiReactions[emoji]} + + ) + })} like()}> -   - {(reactions?.length ?? 0)} +   + {likes} + + dislike()}> +   + {dislikes} console.debug(ev)}> diff --git a/src/feed/EventPublisher.js b/src/feed/EventPublisher.js index 91daa2ac..a8c11dab 100644 --- a/src/feed/EventPublisher.js +++ b/src/feed/EventPublisher.js @@ -83,10 +83,10 @@ export default function useEventPublisher() { } return await signEvent(ev); }, - like: async (evRef) => { + like: async (evRef, content = "+") => { let ev = Event.ForPubKey(pubKey); ev.Kind = EventKind.Reaction; - ev.Content = "+"; + ev.Content = content; ev.Tags.push(new Tag(["e", evRef.Id], 0)); ev.Tags.push(new Tag(["p", evRef.PubKey], 1)); return await signEvent(ev);