From a92d1da7ad84e3f60675e927942ad53618703da0 Mon Sep 17 00:00:00 2001 From: en Date: Thu, 30 Jan 2025 11:12:03 +0100 Subject: [PATCH] fix(comments): move depth calc, parent and root fetch to hook, main post leads to root, add small spinners --- src/components/comment/CommentsPopup.tsx | 27 ++++++++---- src/hooks/index.ts | 1 + src/hooks/useReplies.tsx | 53 ++++++++++++++++++++++++ src/loaders/comment.ts | 28 +------------ src/types/comments.ts | 1 - 5 files changed, 75 insertions(+), 35 deletions(-) create mode 100644 src/hooks/useReplies.tsx diff --git a/src/components/comment/CommentsPopup.tsx b/src/components/comment/CommentsPopup.tsx index 516505f..6cbc6ac 100644 --- a/src/components/comment/CommentsPopup.tsx +++ b/src/components/comment/CommentsPopup.tsx @@ -1,5 +1,5 @@ import { formatDate } from 'date-fns' -import { useBodyScrollDisable, useNDKContext } from 'hooks' +import { useBodyScrollDisable, useNDKContext, useReplies } from 'hooks' import { nip19 } from 'nostr-tools' import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react' import { @@ -19,6 +19,7 @@ import { NDKKind } from '@nostr-dev-kit/ndk' import { Comment } from './Comment' import { useComments } from 'hooks/useComments' import { CommentContent } from './CommentContent' +import { Dots } from 'components/Spinner' export const CommentsPopup = () => { const { naddr } = useParams() @@ -35,7 +36,13 @@ export const CommentsPopup = () => { : undefined : undefined - const { event, parents } = useLoaderData() as CommentsLoaderResult + const { event } = useLoaderData() as CommentsLoaderResult + const { + size, + parent: replyEvent, + isComplete, + root: rootEvent + } = useReplies(event.tagValue('e')) const isRoot = event.tagValue('a') === event.tagValue('A') const [profile, setProfile] = useState() const { commentEvents, setCommentEvents } = useComments( @@ -56,7 +63,6 @@ export const CommentsPopup = () => { [event.pubkey] ) - const replyEvent = parents.length > 0 ? parents[0] : undefined const navigate = useNavigate() const [isSubmitting, setIsSubmitting] = useState(false) @@ -110,6 +116,9 @@ export const CommentsPopup = () => {
{replyEvent && ( @@ -126,16 +135,20 @@ export const CommentsPopup = () => { )}

- Reply Depth: {parents.length} + Reply Depth: {size} + {!isComplete && }

- {!isRoot && ( + {!isRoot && rootEvent && ( - Main Post + Main Post {!isComplete && } )} diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 7746976..b397cf6 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -11,3 +11,4 @@ export * from './useScrollDisable' export * from './useLocalStorage' export * from './useSessionStorage' export * from './useLocalCache' +export * from './useReplies' diff --git a/src/hooks/useReplies.tsx b/src/hooks/useReplies.tsx new file mode 100644 index 0000000..5513d32 --- /dev/null +++ b/src/hooks/useReplies.tsx @@ -0,0 +1,53 @@ +import { + NDKEvent, + NDKKind, + NDKSubscriptionCacheUsage +} from '@nostr-dev-kit/ndk' +import { useState } from 'react' +import { useNDKContext } from './useNDKContext' +import { useDidMount } from './useDidMount' + +export const useReplies = (eTag: string | undefined) => { + const { ndk } = useNDKContext() + const [replies, setReplies] = useState([]) + const [isComplete, setIsComplete] = useState(false) + + useDidMount(async () => { + if (!eTag) { + setIsComplete(true) + return + } + + let eDepth: string | undefined = eTag + while (eDepth) { + const previousReply = await ndk.fetchEvent( + { + kinds: [NDKKind.Text, NDKKind.GenericReply], + ids: [eDepth] + }, + { + cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST + } + ) + if (previousReply) { + setReplies((p) => { + if (p.findIndex((p) => p.id === previousReply.id) === -1) { + p.push(previousReply) + } + return p + }) + eDepth = previousReply.tagValue('e') + } else { + eDepth = undefined + } + } + setIsComplete(true) + }) + + return { + size: replies.length, + isComplete, + parent: replies.length > 0 ? replies[0] : undefined, + root: isComplete ? replies[replies.length - 1] : undefined + } +} diff --git a/src/loaders/comment.ts b/src/loaders/comment.ts index ce12d7c..06fa85c 100644 --- a/src/loaders/comment.ts +++ b/src/loaders/comment.ts @@ -1,8 +1,3 @@ -import { - NDKEvent, - NDKKind, - NDKSubscriptionCacheUsage -} from '@nostr-dev-kit/ndk' import { NDKContextType } from 'contexts/NDKContext' import { LoaderFunctionArgs, redirect } from 'react-router-dom' import { CommentsLoaderResult } from 'types/comments' @@ -25,30 +20,9 @@ export const commentsLoader = throw new Error('We are unable to find the comment on the relays') } - const replies: NDKEvent[] = [] - let eTag: string | undefined = replyEvent.tagValue('e') - while (eTag) { - const prev = await ndkContext.ndk.fetchEvent( - { - kinds: [NDKKind.Text, NDKKind.GenericReply], - ids: [eTag] - }, - { - cacheUsage: NDKSubscriptionCacheUsage.CACHE_FIRST - } - ) - if (prev) { - replies.push(prev) - eTag = prev.tagValue('e') - } else { - eTag = undefined - } - } const result: Partial = { - event: replyEvent, - parents: replies + event: replyEvent } - console.log(replyEvent.content) return result } catch (error) { let message = 'An error occurred in fetching comment from relays' diff --git a/src/types/comments.ts b/src/types/comments.ts index bdde1e4..a14a7f0 100644 --- a/src/types/comments.ts +++ b/src/types/comments.ts @@ -2,7 +2,6 @@ import { NDKEvent } from '@nostr-dev-kit/ndk' export interface CommentsLoaderResult { event: NDKEvent - parents: NDKEvent[] } export enum SortByEnum {