From b3f95366d39d60c5bbec96e9896b585449ea3acf Mon Sep 17 00:00:00 2001 From: Ren Amamiya <123083837+reyamir@users.noreply.github.com> Date: Fri, 17 Mar 2023 13:05:10 +0700 Subject: [PATCH] added note metadta component --- .../counter/comments.tsx} | 38 +------- .../index.tsx => content/counter/likes.tsx} | 88 ++++++++----------- src/components/note/content/index.tsx | 8 +- src/components/note/content/metadata.tsx | 53 +++++++++++ .../note/{form.tsx => form/basic.tsx} | 17 +++- src/components/note/index.tsx | 15 +++- src/components/note/root.tsx | 2 +- src/pages/newsfeed/following.tsx | 6 +- src/pages/newsfeed/thread/index.tsx | 61 +++++++++++++ 9 files changed, 189 insertions(+), 99 deletions(-) rename src/components/note/{reply/index.tsx => content/counter/comments.tsx} (50%) rename src/components/note/{reaction/index.tsx => content/counter/likes.tsx} (53%) create mode 100644 src/components/note/content/metadata.tsx rename src/components/note/{form.tsx => form/basic.tsx} (89%) create mode 100644 src/pages/newsfeed/thread/index.tsx diff --git a/src/components/note/reply/index.tsx b/src/components/note/content/counter/comments.tsx similarity index 50% rename from src/components/note/reply/index.tsx rename to src/components/note/content/counter/comments.tsx index b757e5ac..7ac24662 100644 --- a/src/components/note/reply/index.tsx +++ b/src/components/note/content/counter/comments.tsx @@ -1,38 +1,8 @@ -import { RelayContext } from '@components/contexts/relay'; - -import { useLocalStorage } from '@rehooks/local-storage'; -import { memo, useContext, useEffect, useState } from 'react'; - -export const Reply = memo(function Reply({ eventID }: { eventID: string }) { - const relayPool: any = useContext(RelayContext); - - const [relays]: any = useLocalStorage('relays'); - const [reply, setReply] = useState(0); - - useEffect(() => { - relayPool.subscribe( - [ - { - '#e': [eventID], - since: 0, - kinds: [1], - limit: 10, - }, - ], - relays, - () => { - setReply(reply + 1); - }, - undefined, - (events: any, relayURL: any) => { - console.log(events, relayURL); - } - ); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [eventID, relayPool, relays]); +import { memo } from 'react'; +export const CommentsCounter = memo(function CommentsCounter({ comments }: { comments: number }) { return ( -
+
- {reply} + {comments}
); }); diff --git a/src/components/note/reaction/index.tsx b/src/components/note/content/counter/likes.tsx similarity index 53% rename from src/components/note/reaction/index.tsx rename to src/components/note/content/counter/likes.tsx index 75061089..e0da83d5 100644 --- a/src/components/note/reaction/index.tsx +++ b/src/components/note/content/counter/likes.tsx @@ -4,66 +4,50 @@ import { dateToUnix } from '@utils/getDate'; import { useLocalStorage } from '@rehooks/local-storage'; import { getEventHash, signEvent } from 'nostr-tools'; -import { memo, useContext, useEffect, useState } from 'react'; +import { memo, useCallback, useContext, useState } from 'react'; -export const Reaction = memo(function Reaction({ eventID, eventPubkey }: { eventID: string; eventPubkey: string }) { +export const LikesCounter = memo(function LikesCounter({ + likes, + eventID, + eventPubkey, +}: { + likes: number; + eventID: string; + eventPubkey: string; +}) { const relayPool: any = useContext(RelayContext); + const [relays]: any = useLocalStorage('relays'); - - const [reaction, setReaction] = useState(0); - const [isReact, setIsReact] = useState(false); - const [currentUser]: any = useLocalStorage('current-user'); - const handleReaction = (e: any) => { - e.stopPropagation(); + const [isReact, setIsReact] = useState(false); - const event: any = { - content: '+', - kind: 7, - tags: [ - ['e', eventID], - ['p', eventPubkey], - ], - created_at: dateToUnix(), - pubkey: currentUser.id, - }; - event.id = getEventHash(event); - event.sig = signEvent(event, currentUser.privkey); - // publish event to all relays - relayPool.publish(event, relays); - // update state to change icon to filled heart - setIsReact(true); - // update reaction count - setReaction(reaction + 1); - }; + const handleLike = useCallback( + (e: any) => { + e.stopPropagation(); - useEffect(() => { - relayPool.subscribe( - [ - { - '#e': [eventID], - since: 0, - kinds: [7], - limit: 10, - }, - ], - relays, - (event: any) => { - if (event.content === '🤙' || event.content === '+') { - setReaction(reaction + 1); - } - }, - undefined, - (events: any, relayURL: any) => { - console.log(events, relayURL); - } - ); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [eventID, relayPool, relays]); + const event: any = { + content: '+', + kind: 7, + tags: [ + ['e', eventID], + ['p', eventPubkey], + ], + created_at: dateToUnix(), + pubkey: currentUser.id, + }; + event.id = getEventHash(event); + event.sig = signEvent(event, currentUser.privkey); + // publish event to all relays + relayPool.publish(event, relays); + // update state to change icon to filled heart + setIsReact(true); + }, + [currentUser.id, currentUser.privkey, eventID, eventPubkey, relayPool, relays] + ); return ( - ); }); diff --git a/src/components/note/content/index.tsx b/src/components/note/content/index.tsx index 998c306e..859ea39f 100644 --- a/src/components/note/content/index.tsx +++ b/src/components/note/content/index.tsx @@ -1,7 +1,6 @@ +import NoteMetadata from '@components/note/content/metadata'; import { ImageCard } from '@components/note/content/preview/imageCard'; import { Video } from '@components/note/content/preview/video'; -import { Reaction } from '@components/note/reaction'; -import { Reply } from '@components/note/reply'; import { UserExtend } from '@components/user/extend'; import dynamic from 'next/dynamic'; @@ -87,10 +86,7 @@ export const Content = memo(function Content({ data }: { data: any }) {
<>{previewAttachment()} -
- - -
+ diff --git a/src/components/note/content/metadata.tsx b/src/components/note/content/metadata.tsx new file mode 100644 index 00000000..f9094e95 --- /dev/null +++ b/src/components/note/content/metadata.tsx @@ -0,0 +1,53 @@ +import { RelayContext } from '@components/contexts/relay'; +import { CommentsCounter } from '@components/note/content/counter/comments'; +import { LikesCounter } from '@components/note/content/counter/likes'; + +import { useLocalStorage } from '@rehooks/local-storage'; +import { useContext, useMemo, useState } from 'react'; + +export default function NoteMetadata({ eventID, eventPubkey }: { eventID: string; eventPubkey: string }) { + const relayPool: any = useContext(RelayContext); + const [relays]: any = useLocalStorage('relays'); + + const [likes, setLikes] = useState(0); + const [comments, setComments] = useState(0); + + useMemo(() => { + relayPool.subscribe( + [ + { + '#e': [eventID], + since: 0, + kinds: [1, 7], + }, + ], + relays, + (event: any) => { + switch (event.kind) { + case 1: + setComments((comments) => (comments += 1)); + break; + case 7: + if (event.content === '🤙' || event.content === '+') { + setLikes((likes) => (likes += 1)); + } + break; + default: + break; + } + }, + undefined, + (events: any, relayURL: any) => { + console.log(events, relayURL); + } + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [eventID, relayPool, relays]); + + return ( +
+ + +
+ ); +} diff --git a/src/components/note/form.tsx b/src/components/note/form/basic.tsx similarity index 89% rename from src/components/note/form.tsx rename to src/components/note/form/basic.tsx index aa9083bb..f4d7166e 100644 --- a/src/components/note/form.tsx +++ b/src/components/note/form/basic.tsx @@ -14,7 +14,7 @@ const MDEditor = dynamic(() => import('@uiw/react-md-editor').then((mod) => mod. ssr: false, }); -export default function NoteForm() { +export default function FormBasic() { const relayPool: any = useContext(RelayContext); const [relays]: any = useLocalStorage('relays'); @@ -95,7 +95,20 @@ export default function NoteForm() { - + + + diff --git a/src/components/note/index.tsx b/src/components/note/index.tsx index 735fb10b..a1ff8d16 100644 --- a/src/components/note/index.tsx +++ b/src/components/note/index.tsx @@ -1,12 +1,22 @@ import { Content } from '@components/note/content'; import { RootNote } from '@components/note/root'; +import { useRouter } from 'next/router'; import { memo, useEffect, useState } from 'react'; export const Note = memo(function Note({ event }: { event: any }) { + const router = useRouter(); + const [root, setRoot] = useState(null); const tags = JSON.parse(event.tags); + const openThread = () => { + router.push({ + pathname: '/newsfeed/thread', + query: { id: root ? root : event.id }, + }); + }; + useEffect(() => { if (tags.length > 0) { if (tags[0][0] === 'e') { @@ -16,7 +26,10 @@ export const Note = memo(function Note({ event }: { event: any }) { }, [tags]); return ( -
+
openThread()} + className="relative z-10 flex h-min min-h-min w-full cursor-pointer select-text flex-col border-b border-zinc-800 py-5 px-3 hover:bg-black/20" + > {root && ( <> diff --git a/src/components/note/root.tsx b/src/components/note/root.tsx index 97893162..36e3090a 100644 --- a/src/components/note/root.tsx +++ b/src/components/note/root.tsx @@ -32,7 +32,7 @@ export const RootNote = memo(function RootNote({ id }: { id: string }) { if (event) { return (
-
+
); diff --git a/src/pages/newsfeed/following.tsx b/src/pages/newsfeed/following.tsx index b2f864fc..b0a59068 100644 --- a/src/pages/newsfeed/following.tsx +++ b/src/pages/newsfeed/following.tsx @@ -3,7 +3,7 @@ import WithSidebarLayout from '@layouts/withSidebar'; import { DatabaseContext } from '@components/contexts/database'; import { Note } from '@components/note'; -import NoteForm from '@components/note/form'; +import FormBasic from '@components/note/form/basic'; import { Placeholder } from '@components/note/placeholder'; import { atomHasNewerNote } from '@stores/note'; @@ -102,7 +102,7 @@ export default function Page() {
@@ -112,7 +112,7 @@ export default function Page() { data={data} itemContent={ItemContent} components={{ - Header: () => , + Header: () => , EmptyPlaceholder: () => , ScrollSeekPlaceholder: () => , }} diff --git a/src/pages/newsfeed/thread/index.tsx b/src/pages/newsfeed/thread/index.tsx new file mode 100644 index 00000000..bbd801ee --- /dev/null +++ b/src/pages/newsfeed/thread/index.tsx @@ -0,0 +1,61 @@ +import BaseLayout from '@layouts/base'; +import WithSidebarLayout from '@layouts/withSidebar'; + +import { DatabaseContext } from '@components/contexts/database'; +import { Content } from '@components/note/content'; +import FormBasic from '@components/note/form/basic'; + +import { useRouter } from 'next/router'; +import { + JSXElementConstructor, + ReactElement, + ReactFragment, + ReactPortal, + useCallback, + useContext, + useEffect, + useState, +} from 'react'; + +export default function Page() { + const { db }: any = useContext(DatabaseContext); + + const [root, setRoot] = useState(null); + + const router = useRouter(); + const { id }: any = router.query; + + const fetchRoot = useCallback(async () => { + const result = await db.select(`SELECT * FROM cache_notes WHERE id = "${id}"`); + setRoot(result[0]); + }, [db, id]); + + useEffect(() => { + fetchRoot().catch(console.error); + }, [fetchRoot]); + + return ( +
+
{root && }
+
+ +
+
+ ); +} + +Page.getLayout = function getLayout( + page: + | string + | number + | boolean + | ReactElement> + | ReactFragment + | ReactPortal +) { + return ( + + {page} + + ); +};