feat: poll response notification

This commit is contained in:
codytseng 2025-07-28 22:33:51 +08:00
parent 20c712c56b
commit bcd149b304
14 changed files with 209 additions and 93 deletions

View file

@ -0,0 +1,47 @@
import { useFetchEvent } from '@/hooks'
import { toNote } from '@/lib/link'
import { generateBech32IdFromETag, tagNameEquals } from '@/lib/tag'
import { cn } from '@/lib/utils'
import { useSecondaryPage } from '@/PageManager'
import { Vote } from 'lucide-react'
import { Event } from 'nostr-tools'
import { useMemo } from 'react'
import ContentPreview from '../../ContentPreview'
import { FormattedTimestamp } from '../../FormattedTimestamp'
import UserAvatar from '../../UserAvatar'
export function PollResponseNotification({
notification,
isNew = false
}: {
notification: Event
isNew?: boolean
}) {
const { push } = useSecondaryPage()
const eventId = useMemo(() => {
const eTag = notification.tags.find(tagNameEquals('e'))
return eTag ? generateBech32IdFromETag(eTag) : undefined
}, [notification])
const { event: pollEvent } = useFetchEvent(eventId)
if (!pollEvent) {
return null
}
return (
<div
className="flex gap-2 items-center cursor-pointer py-2"
onClick={() => push(toNote(pollEvent))}
>
<UserAvatar userId={notification.pubkey} size="small" />
<Vote size={24} className="text-violet-400" />
<ContentPreview
className={cn('truncate flex-1 w-0', isNew ? 'font-semibold' : 'text-muted-foreground')}
event={pollEvent}
/>
<div className="text-muted-foreground">
<FormattedTimestamp timestamp={notification.created_at} short />
</div>
</div>
)
}

View file

@ -1,7 +1,7 @@
import Image from '@/components/Image'
import { useFetchEvent } from '@/hooks'
import { toNote } from '@/lib/link'
import { tagNameEquals } from '@/lib/tag'
import { generateBech32IdFromETag, tagNameEquals } from '@/lib/tag'
import { cn } from '@/lib/utils'
import { useSecondaryPage } from '@/PageManager'
import { useNostr } from '@/providers/NostrProvider'
@ -26,7 +26,7 @@ export function ReactionNotification({
if (targetPubkey !== pubkey) return undefined
const eTag = notification.tags.findLast(tagNameEquals('e'))
return eTag?.[1]
return eTag ? generateBech32IdFromETag(eTag) : undefined
}, [notification, pubkey])
const { event } = useFetchEvent(eventId)
const reaction = useMemo(() => {

View file

@ -2,6 +2,7 @@ import { ExtendedKind } from '@/constants'
import { useMuteList } from '@/providers/MuteListProvider'
import { Event, kinds } from 'nostr-tools'
import { CommentNotification } from './CommentNotification'
import { PollResponseNotification } from './PollResponseNotification'
import { ReactionNotification } from './ReactionNotification'
import { ReplyNotification } from './ReplyNotification'
import { RepostNotification } from './RepostNotification'
@ -33,5 +34,8 @@ export function NotificationItem({
if (notification.kind === ExtendedKind.COMMENT) {
return <CommentNotification notification={notification} isNew={isNew} />
}
if (notification.kind === ExtendedKind.POLL_RESPONSE) {
return <PollResponseNotification notification={notification} isNew={isNew} />
}
return null
}