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