diff --git a/src/components/NotificationList/NotificationItem/CommentNotification.tsx b/src/components/NotificationList/NotificationItem/CommentNotification.tsx index 33e6dd4c..05bd091f 100644 --- a/src/components/NotificationList/NotificationItem/CommentNotification.tsx +++ b/src/components/NotificationList/NotificationItem/CommentNotification.tsx @@ -1,10 +1,8 @@ -import { ExtendedKind } from '@/constants' import { toNote } from '@/lib/link' -import { tagNameEquals } from '@/lib/tag' import { cn } from '@/lib/utils' import { useSecondaryPage } from '@/PageManager' import { MessageCircle } from 'lucide-react' -import { Event, kinds } from 'nostr-tools' +import { Event } from 'nostr-tools' import ContentPreview from '../../ContentPreview' import { FormattedTimestamp } from '../../FormattedTimestamp' import UserAvatar from '../../UserAvatar' @@ -17,22 +15,11 @@ export function CommentNotification({ isNew?: boolean }) { const { push } = useSecondaryPage() - const rootEventId = notification.tags.find(tagNameEquals('E'))?.[1] - const rootPubkey = notification.tags.find(tagNameEquals('P'))?.[1] - const rootKind = notification.tags.find(tagNameEquals('K'))?.[1] - if ( - !rootEventId || - !rootPubkey || - !rootKind || - ![kinds.ShortTextNote, ExtendedKind.PICTURE].includes(parseInt(rootKind)) - ) { - return null - } return (
push(toNote({ id: rootEventId, pubkey: rootPubkey }))} + onClick={() => push(toNote(notification))} > diff --git a/src/components/ReplyNoteList/index.tsx b/src/components/ReplyNoteList/index.tsx index 96daee9f..0a326686 100644 --- a/src/components/ReplyNoteList/index.tsx +++ b/src/components/ReplyNoteList/index.tsx @@ -6,7 +6,7 @@ import { getRootEventTag, isReplyNoteEvent } from '@/lib/event' -import { generateEventIdFromETag } from '@/lib/tag' +import { generateEventIdFromETag, tagNameEquals } from '@/lib/tag' import { useSecondaryPage } from '@/PageManager' import { useReply } from '@/providers/ReplyProvider' import client from '@/services/client.service' @@ -15,6 +15,8 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import ReplyNote from '../ReplyNote' +type TRootInfo = { type: 'event'; id: string; pubkey: string } | { type: 'I'; id: string } + const LIMIT = 100 const SHOW_COUNT = 10 @@ -29,7 +31,7 @@ export default function ReplyNoteList({ }) { const { t } = useTranslation() const { currentIndex } = useSecondaryPage() - const [rootInfo, setRootInfo] = useState<{ id: string; pubkey: string } | undefined>(undefined) + const [rootInfo, setRootInfo] = useState(undefined) const { repliesMap, addReplies } = useReply() const replies = useMemo(() => { const replyIdSet = new Set() @@ -56,21 +58,26 @@ export default function ReplyNoteList({ useEffect(() => { const fetchRootEvent = async () => { - let root = { id: event.id, pubkey: event.pubkey } + let root: TRootInfo = { type: 'event', id: event.id, pubkey: event.pubkey } const rootEventTag = getRootEventTag(event) if (rootEventTag) { const [, rootEventHexId, , , rootEventPubkey] = rootEventTag if (rootEventHexId && rootEventPubkey) { - root = { id: rootEventHexId, pubkey: rootEventPubkey } + root = { type: 'event', id: rootEventHexId, pubkey: rootEventPubkey } } else { const rootEventId = generateEventIdFromETag(rootEventTag) if (rootEventId) { const rootEvent = await client.fetchEvent(rootEventId) if (rootEvent) { - root = { id: rootEvent.id, pubkey: rootEvent.pubkey } + root = { type: 'event', id: rootEvent.id, pubkey: rootEvent.pubkey } } } } + } else if (event.kind === ExtendedKind.COMMENT) { + const rootITag = event.tags.find(tagNameEquals('I')) + if (rootITag) { + root = { type: 'I', id: rootITag[1] } + } } setRootInfo(root) } @@ -105,23 +112,32 @@ export default function ReplyNoteList({ setLoading(true) try { - const relayList = await client.fetchRelayList(rootInfo.pubkey) + const relayList = await client.fetchRelayList( + (rootInfo as { pubkey?: string }).pubkey ?? event.pubkey + ) const relayUrls = relayList.read.concat(BIG_RELAY_URLS) const seenOn = client.getSeenEventRelayUrls(rootInfo.id) relayUrls.unshift(...seenOn) const filters: (Omit & { limit: number - })[] = [ - { + })[] = [] + if (rootInfo.type === 'event') { + filters.push({ '#e': [rootInfo.id], kinds: [kinds.ShortTextNote], limit: LIMIT + }) + if (event.kind !== kinds.ShortTextNote) { + filters.push({ + '#E': [rootInfo.id], + kinds: [ExtendedKind.COMMENT], + limit: LIMIT + }) } - ] - if (event.kind !== kinds.ShortTextNote) { + } else { filters.push({ - '#E': [rootInfo.id], + '#I': [rootInfo.id], kinds: [ExtendedKind.COMMENT], limit: LIMIT }) diff --git a/src/lib/event.ts b/src/lib/event.ts index 89f703b2..e3a46863 100644 --- a/src/lib/event.ts +++ b/src/lib/event.ts @@ -354,15 +354,15 @@ export async function extractRelatedEventIds(content: string, parentEvent?: Even export async function extractCommentMentions(content: string, parentEvent: Event) { const quoteEventIds: string[] = [] - let rootEventId = + const rootEventId = parentEvent.kind === ExtendedKind.COMMENT ? parentEvent.tags.find(tagNameEquals('E'))?.[1] : parentEvent.id - let rootKind = + const rootKind = parentEvent.kind === ExtendedKind.COMMENT ? parentEvent.tags.find(tagNameEquals('K'))?.[1] : parentEvent.kind - let rootPubkey = + const rootPubkey = parentEvent.kind === ExtendedKind.COMMENT ? parentEvent.tags.find(tagNameEquals('P'))?.[1] : parentEvent.pubkey @@ -371,12 +371,6 @@ export async function extractCommentMentions(content: string, parentEvent: Event ? parentEvent.tags.find(tagNameEquals('I'))?.[1] : undefined - if (parentEvent.kind === ExtendedKind.COMMENT && !rootEventId) { - rootEventId = parentEvent.id - rootKind = parentEvent.kind - rootPubkey = parentEvent.pubkey - } - const parentEventId = parentEvent.id const parentKind = parentEvent.kind const parentPubkey = parentEvent.pubkey diff --git a/src/pages/secondary/NotePage/index.tsx b/src/pages/secondary/NotePage/index.tsx index 4a3eb3bf..da405f8f 100644 --- a/src/pages/secondary/NotePage/index.tsx +++ b/src/pages/secondary/NotePage/index.tsx @@ -8,10 +8,12 @@ import UserAvatar from '@/components/UserAvatar' import { Card } from '@/components/ui/card' import { Separator } from '@/components/ui/separator' import { Skeleton } from '@/components/ui/skeleton' +import { ExtendedKind } from '@/constants' import { useFetchEvent } from '@/hooks' import SecondaryPageLayout from '@/layouts/SecondaryPageLayout' import { getParentEventId, getRootEventId, isPictureEvent } from '@/lib/event' import { toNote } from '@/lib/link' +import { tagNameEquals } from '@/lib/tag' import { useMuteList } from '@/providers/MuteListProvider' import { forwardRef, useMemo } from 'react' import { useTranslation } from 'react-i18next' @@ -22,6 +24,10 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref const { event, isFetching } = useFetchEvent(id) const parentEventId = useMemo(() => getParentEventId(event), [event]) const rootEventId = useMemo(() => getRootEventId(event), [event]) + const rootITag = useMemo( + () => (event?.kind === ExtendedKind.COMMENT ? event.tags.find(tagNameEquals('I')) : undefined), + [event] + ) if (!event && isFetching) { return ( @@ -65,7 +71,8 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref return (
- {rootEventId !== parentEventId && ( + {rootITag && } + {!rootITag && rootEventId !== parentEventId && ( )} @@ -85,6 +92,33 @@ const NotePage = forwardRef(({ id, index }: { id?: string; index?: number }, ref NotePage.displayName = 'NotePage' export default NotePage +function OtherRoot({ value }: { value: string }) { + const type = useMemo(() => (value.startsWith('http') ? 'url' : 'other'), [value]) + + if (type === 'url') { + return ( +
+ window.open(value, '_blank')} + > +
{value}
+
+
+
+ ) + } + + return ( +
+ +
{value}
+
+
+
+ ) +} + function ParentNote({ eventId }: { eventId?: string }) { const { t } = useTranslation() const { push } = useSecondaryPage() diff --git a/src/providers/ReplyProvider.tsx b/src/providers/ReplyProvider.tsx index 2a9d8df0..b7c3e335 100644 --- a/src/providers/ReplyProvider.tsx +++ b/src/providers/ReplyProvider.tsx @@ -30,14 +30,16 @@ export function ReplyProvider({ children }: { children: React.ReactNode }) { newReplyIdSet.add(reply.id) const rootETag = getRootEventTag(reply) - if (!rootETag) return - const rootId = rootETag[1] - newReplyEventMap.set(rootId, [...(newReplyEventMap.get(rootId) || []), reply]) + if (rootETag) { + const rootId = rootETag[1] + newReplyEventMap.set(rootId, [...(newReplyEventMap.get(rootId) || []), reply]) + } const parentETag = getParentEventTag(reply) - if (!parentETag) return - const parentId = parentETag[1] - newReplyEventMap.set(parentId, [...(newReplyEventMap.get(parentId) || []), reply]) + if (parentETag) { + const parentId = parentETag[1] + newReplyEventMap.set(parentId, [...(newReplyEventMap.get(parentId) || []), reply]) + } }) if (newReplyEventMap.size === 0) return