diff --git a/src/components/NotificationList/NotificationItem/CommentNotification.tsx b/src/components/NotificationList/NotificationItem/MentionNotification.tsx similarity index 60% rename from src/components/NotificationList/NotificationItem/CommentNotification.tsx rename to src/components/NotificationList/NotificationItem/MentionNotification.tsx index 05bd091f..d76aef23 100644 --- a/src/components/NotificationList/NotificationItem/CommentNotification.tsx +++ b/src/components/NotificationList/NotificationItem/MentionNotification.tsx @@ -1,13 +1,16 @@ +import { getEmbeddedPubkeys } from '@/lib/event' import { toNote } from '@/lib/link' import { cn } from '@/lib/utils' import { useSecondaryPage } from '@/PageManager' -import { MessageCircle } from 'lucide-react' +import { useNostr } from '@/providers/NostrProvider' +import { AtSign, MessageCircle } 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 CommentNotification({ +export function MentionNotification({ notification, isNew = false }: { @@ -15,6 +18,12 @@ export function CommentNotification({ isNew?: boolean }) { const { push } = useSecondaryPage() + const { pubkey } = useNostr() + const isMention = useMemo(() => { + if (!pubkey) return false + const mentions = getEmbeddedPubkeys(notification) + return mentions.includes(pubkey) + }, [pubkey, notification]) return (
push(toNote(notification))} > - + {isMention ? ( + + ) : ( + + )} push(toNote(notification))} - > - - - -
- -
-
- ) -} diff --git a/src/components/NotificationList/NotificationItem/index.tsx b/src/components/NotificationList/NotificationItem/index.tsx index 8349da96..b86c8e86 100644 --- a/src/components/NotificationList/NotificationItem/index.tsx +++ b/src/components/NotificationList/NotificationItem/index.tsx @@ -1,10 +1,9 @@ import { ExtendedKind } from '@/constants' import { useMuteList } from '@/providers/MuteListProvider' import { Event, kinds } from 'nostr-tools' -import { CommentNotification } from './CommentNotification' +import { MentionNotification } from './MentionNotification' import { PollResponseNotification } from './PollResponseNotification' import { ReactionNotification } from './ReactionNotification' -import { ReplyNotification } from './ReplyNotification' import { RepostNotification } from './RepostNotification' import { ZapNotification } from './ZapNotification' @@ -22,8 +21,13 @@ export function NotificationItem({ if (notification.kind === kinds.Reaction) { return } - if (notification.kind === kinds.ShortTextNote) { - return + if ( + notification.kind === kinds.ShortTextNote || + notification.kind === ExtendedKind.COMMENT || + notification.kind === ExtendedKind.VOICE_COMMENT || + notification.kind === ExtendedKind.POLL + ) { + return } if (notification.kind === kinds.Repost) { return @@ -31,12 +35,6 @@ export function NotificationItem({ if (notification.kind === kinds.Zap) { return } - if ( - notification.kind === ExtendedKind.COMMENT || - notification.kind === ExtendedKind.VOICE_COMMENT - ) { - return - } if (notification.kind === ExtendedKind.POLL_RESPONSE) { return } diff --git a/src/components/NotificationList/index.tsx b/src/components/NotificationList/index.tsx index 75a9d552..f01a496e 100644 --- a/src/components/NotificationList/index.tsx +++ b/src/components/NotificationList/index.tsx @@ -39,7 +39,12 @@ const NotificationList = forwardRef((_, ref) => { const filterKinds = useMemo(() => { switch (notificationType) { case 'mentions': - return [kinds.ShortTextNote, ExtendedKind.COMMENT, ExtendedKind.VOICE_COMMENT] + return [ + kinds.ShortTextNote, + ExtendedKind.COMMENT, + ExtendedKind.VOICE_COMMENT, + ExtendedKind.POLL + ] case 'reactions': return [kinds.Reaction, kinds.Repost, ExtendedKind.POLL_RESPONSE] case 'zaps': @@ -52,7 +57,8 @@ const NotificationList = forwardRef((_, ref) => { kinds.Zap, ExtendedKind.COMMENT, ExtendedKind.POLL_RESPONSE, - ExtendedKind.VOICE_COMMENT + ExtendedKind.VOICE_COMMENT, + ExtendedKind.POLL ] } }, [notificationType]) diff --git a/src/lib/event.ts b/src/lib/event.ts index 18756c99..32e80060 100644 --- a/src/lib/event.ts +++ b/src/lib/event.ts @@ -1,4 +1,4 @@ -import { ExtendedKind } from '@/constants' +import { EMBEDDED_MENTION_REGEX, ExtendedKind } from '@/constants' import client from '@/services/client.service' import { TImageInfo } from '@/types' import { LRUCache } from 'lru-cache' @@ -11,6 +11,7 @@ import { } from './tag' const EVENT_EMBEDDED_NOTES_CACHE = new LRUCache({ max: 10000 }) +const EVENT_EMBEDDED_PUBKEYS_CACHE = new LRUCache({ max: 10000 }) const EVENT_IS_REPLY_NOTE_CACHE = new LRUCache({ max: 10000 }) export function isNsfwEvent(event: Event) { @@ -199,6 +200,28 @@ export function getEmbeddedNoteBech32Ids(event: Event) { return embeddedNoteBech32Ids } +export function getEmbeddedPubkeys(event: Event) { + const cache = EVENT_EMBEDDED_PUBKEYS_CACHE.get(event.id) + if (cache) return cache + + const embeddedPubkeySet = new Set() + ;(event.content.match(EMBEDDED_MENTION_REGEX) || []).forEach((mention) => { + try { + const { type, data } = nip19.decode(mention.split(':')[1]) + if (type === 'npub') { + embeddedPubkeySet.add(data) + } else if (type === 'nprofile') { + embeddedPubkeySet.add(data.pubkey) + } + } catch { + // ignore + } + }) + const embeddedPubkeys = Array.from(embeddedPubkeySet) + EVENT_EMBEDDED_PUBKEYS_CACHE.set(event.id, embeddedPubkeys) + return embeddedPubkeys +} + export function getLatestEvent(events: Event[]) { return events.sort((a, b) => b.created_at - a.created_at)[0] }