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