index.tsx raw

   1  import NoteCard from '@/components/NoteCard'
   2  import { SimpleUsername } from '@/components/Username'
   3  import SecondaryPageLayout from '@/layouts/SecondaryPageLayout'
   4  import userAggregationService from '@/services/user-aggregation.service'
   5  import { nip19, NostrEvent } from 'nostr-tools'
   6  import { forwardRef, useEffect, useMemo, useState } from 'react'
   7  import { useTranslation } from 'react-i18next'
   8  
   9  const UserAggregationDetailPage = forwardRef(
  10    (
  11      {
  12        feedId,
  13        npub,
  14        index
  15      }: {
  16        feedId?: string
  17        npub?: string
  18        index?: number
  19      },
  20      ref
  21    ) => {
  22      const { t } = useTranslation()
  23      const [aggregation, setAggregation] = useState<NostrEvent[]>([])
  24  
  25      const pubkey = useMemo(() => {
  26        if (!npub) return undefined
  27        try {
  28          const { type, data } = nip19.decode(npub)
  29          if (type === 'npub') return data
  30          if (type === 'nprofile') return data.pubkey
  31        } catch {
  32          return undefined
  33        }
  34      }, [npub])
  35  
  36      useEffect(() => {
  37        if (!feedId || !pubkey) {
  38          setAggregation([])
  39          return
  40        }
  41  
  42        const updateEvents = () => {
  43          const events = userAggregationService.getAggregation(feedId, pubkey)
  44          setAggregation(events)
  45        }
  46  
  47        const unSub = userAggregationService.subscribeAggregationChange(feedId, pubkey, () => {
  48          updateEvents()
  49        })
  50  
  51        updateEvents()
  52  
  53        return unSub
  54      }, [feedId, pubkey, setAggregation])
  55  
  56      if (!pubkey || !feedId) {
  57        return (
  58          <SecondaryPageLayout ref={ref} index={index} title={t('User Posts')}>
  59            <div className="flex justify-center items-center h-40 text-muted-foreground">
  60              {t('Invalid user')}
  61            </div>
  62          </SecondaryPageLayout>
  63        )
  64      }
  65  
  66      return (
  67        <SecondaryPageLayout
  68          ref={ref}
  69          index={index}
  70          title={<SimpleUsername userId={pubkey} className="truncate" />}
  71          displayScrollToTopButton
  72        >
  73          <div className="min-h-screen">
  74            {aggregation.map((event) => (
  75              <NoteCard key={event.id} className="w-full" event={event} filterMutedNotes={false} />
  76            ))}
  77            <div className="text-center text-sm text-muted-foreground mt-2">{t('no more notes')}</div>
  78          </div>
  79        </SecondaryPageLayout>
  80      )
  81    }
  82  )
  83  
  84  UserAggregationDetailPage.displayName = 'UserAggregationDetailPage'
  85  
  86  export default UserAggregationDetailPage
  87