RepostNoteCard.tsx raw
1 import { isMentioningMutedUsers } from '@/lib/event'
2 import { generateBech32IdFromATag, generateBech32IdFromETag, tagNameEquals } from '@/lib/tag'
3 import { useContentPolicy } from '@/providers/ContentPolicyProvider'
4 import { TNavigationColumn } from '@/providers/KeyboardNavigationProvider'
5 import { useMuteList } from '@/providers/MuteListProvider'
6 import client from '@/services/client.service'
7 import { Event, kinds, verifyEvent } from 'nostr-tools'
8 import { useEffect, useMemo, useState } from 'react'
9 import MainNoteCard from './MainNoteCard'
10
11 export default function RepostNoteCard({
12 event,
13 className,
14 filterMutedNotes = true,
15 pinned = false,
16 reposters,
17 navColumn,
18 navIndex
19 }: {
20 event: Event
21 className?: string
22 filterMutedNotes?: boolean
23 pinned?: boolean
24 reposters?: string[]
25 navColumn?: TNavigationColumn
26 navIndex?: number
27 }) {
28 const { mutePubkeySet } = useMuteList()
29 const { hideContentMentioningMutedUsers } = useContentPolicy()
30 const [targetEvent, setTargetEvent] = useState<Event | null>(null)
31 const shouldHide = useMemo(() => {
32 if (!targetEvent) return true
33 if (filterMutedNotes && mutePubkeySet.has(targetEvent.pubkey)) {
34 return true
35 }
36 if (hideContentMentioningMutedUsers && isMentioningMutedUsers(targetEvent, mutePubkeySet)) {
37 return true
38 }
39 return false
40 }, [targetEvent, filterMutedNotes, hideContentMentioningMutedUsers, mutePubkeySet])
41 useEffect(() => {
42 const fetch = async () => {
43 let eventFromContent: Event | null = null
44 if (event.content) {
45 try {
46 eventFromContent = JSON.parse(event.content) as Event
47 } catch {
48 eventFromContent = null
49 }
50 }
51 if (eventFromContent && verifyEvent(eventFromContent)) {
52 if (
53 eventFromContent.kind === kinds.Repost ||
54 eventFromContent.kind === kinds.GenericRepost
55 ) {
56 return
57 }
58 client.addEventToCache(eventFromContent)
59 const targetSeenOn = client.getSeenEventRelays(eventFromContent.id)
60 if (targetSeenOn.length === 0) {
61 const seenOn = client.getSeenEventRelays(event.id)
62 seenOn.forEach((relay) => {
63 client.trackEventSeenOn(eventFromContent.id, relay)
64 })
65 }
66 setTargetEvent(eventFromContent)
67 return
68 }
69
70 let targetEventId: string | undefined
71 const aTag = event.tags.find(tagNameEquals('a'))
72 if (aTag) {
73 targetEventId = generateBech32IdFromATag(aTag)
74 } else {
75 const eTag = event.tags.find(tagNameEquals('e'))
76 if (eTag) {
77 targetEventId = generateBech32IdFromETag(eTag)
78 }
79 }
80 if (!targetEventId) {
81 return
82 }
83
84 const targetEvent = await client.fetchEvent(targetEventId)
85 if (targetEvent) {
86 setTargetEvent(targetEvent)
87 }
88 }
89 fetch()
90 }, [event])
91
92 if (!targetEvent || shouldHide) return null
93
94 return (
95 <MainNoteCard
96 className={className}
97 reposters={reposters?.includes(event.pubkey) ? reposters : [event.pubkey]}
98 event={targetEvent}
99 pinned={pinned}
100 navColumn={navColumn}
101 navIndex={navIndex}
102 />
103 )
104 }
105