From e724c6ba215a6a119352ceaedcaf234078e9fdbd Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Fri, 6 Jan 2023 16:48:50 +0100 Subject: [PATCH 1/4] feat: add support for positive and negative reactions --- src/element/Note.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/element/Note.js b/src/element/Note.js index 64df27b6..c0bfb6b9 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,6 +20,8 @@ export default function Note(props) { const dataEvent = props["data-ev"]; const reactions = props.reactions; const deletion = props.deletion; + const likes = reactions?.filter(({ 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); @@ -77,6 +79,11 @@ export default function Note(props) { 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); @@ -117,7 +124,11 @@ export default function Note(props) { like()}>   - {(reactions?.length ?? 0)} + {likes} + + dislike()}> +   + {dislikes} console.debug(ev)}> From 4680397e1abe7a477af57c8d2feea167422074b4 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Fri, 6 Jan 2023 16:58:31 +0100 Subject: [PATCH 2/4] fix: count shaka likes --- src/element/Note.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/element/Note.js b/src/element/Note.js index c0bfb6b9..b700a679 100644 --- a/src/element/Note.js +++ b/src/element/Note.js @@ -20,7 +20,7 @@ export default function Note(props) { const dataEvent = props["data-ev"]; const reactions = props.reactions; const deletion = props.deletion; - const likes = reactions?.filter(({ Content }) => Content === "+").length ?? 0 + 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); From 1c6176a397d97d96601862b374a3e8eec7b56bca Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Fri, 6 Jan 2023 17:04:04 +0100 Subject: [PATCH 3/4] feat: highlight your reactions on notes --- src/element/Note.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/element/Note.js b/src/element/Note.js index b700a679..f5ff037d 100644 --- a/src/element/Note.js +++ b/src/element/Note.js @@ -28,6 +28,8 @@ export default function Note(props) { 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 === "+" || Content === "🤙" && PubKey === login) + const disliked = reactions?.find(({ PubKey, Content }) => Content === "+" && PubKey === login) const options = { showHeader: true, @@ -123,11 +125,11 @@ export default function Note(props) { like()}> -   +   {likes} dislike()}> -   +   {dislikes} console.debug(ev)}> From e2b9b2223ff550c4090f77bc4ca4049e467208a5 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Fri, 6 Jan 2023 23:10:18 +0100 Subject: [PATCH 4/4] add emoji reactions --- src/element/Note.js | 31 ++++++++++++++++++++++++++++--- src/feed/EventPublisher.js | 4 ++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/element/Note.js b/src/element/Note.js index f5ff037d..833a8d87 100644 --- a/src/element/Note.js +++ b/src/element/Note.js @@ -20,7 +20,12 @@ export default function Note(props) { const dataEvent = props["data-ev"]; const reactions = props.reactions; const deletion = props.deletion; - const likes = reactions?.filter(({ Content }) => Content === "+" || Content === "🤙").length ?? 0 + 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); @@ -28,8 +33,8 @@ export default function Note(props) { 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 === "+" || Content === "🤙" && PubKey === login) - const disliked = reactions?.find(({ PubKey, Content }) => Content === "+" && PubKey === login) + const liked = reactions?.find(({ PubKey, Content }) => Content === "+" && PubKey === login) + const disliked = reactions?.find(({ PubKey, Content }) => Content === "-" && PubKey === login) const options = { showHeader: true, @@ -38,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 ?? ""; @@ -76,6 +85,11 @@ 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); @@ -124,6 +138,17 @@ export default function Note(props) { setShowReply(!showReply)}> + {Object.keys(emojiReactions).map((emoji) => { + return ( + react(emoji)}> + + {emoji} + +   + {emojiReactions[emoji]} + + ) + })} like()}>   {likes} diff --git a/src/feed/EventPublisher.js b/src/feed/EventPublisher.js index 288ca4b9..159427d5 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);