feat: 💨
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import Image from '@/components/Image'
|
import Image from '@/components/Image'
|
||||||
import { useFetchEvent } from '@/hooks'
|
import { useFetchEvent } from '@/hooks'
|
||||||
import { generateBech32IdFromETag, tagNameEquals } from '@/lib/tag'
|
import { generateBech32IdFromATag, generateBech32IdFromETag, tagNameEquals } from '@/lib/tag'
|
||||||
import { useNostr } from '@/providers/NostrProvider'
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
import { Heart } from 'lucide-react'
|
import { Heart } from 'lucide-react'
|
||||||
import { Event } from 'nostr-tools'
|
import { Event } from 'nostr-tools'
|
||||||
@@ -18,9 +18,10 @@ export function ReactionNotification({
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { pubkey } = useNostr()
|
const { pubkey } = useNostr()
|
||||||
const eventId = useMemo(() => {
|
const eventId = useMemo(() => {
|
||||||
const targetPubkey = notification.tags.findLast(tagNameEquals('p'))?.[1]
|
const aTag = notification.tags.findLast(tagNameEquals('a'))
|
||||||
if (targetPubkey !== pubkey) return undefined
|
if (aTag) {
|
||||||
|
return generateBech32IdFromATag(aTag)
|
||||||
|
}
|
||||||
const eTag = notification.tags.findLast(tagNameEquals('e'))
|
const eTag = notification.tags.findLast(tagNameEquals('e'))
|
||||||
return eTag ? generateBech32IdFromETag(eTag) : undefined
|
return eTag ? generateBech32IdFromETag(eTag) : undefined
|
||||||
}, [notification, pubkey])
|
}, [notification, pubkey])
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { ExtendedKind } from '@/constants'
|
import { ExtendedKind } from '@/constants'
|
||||||
import { isMentioningMutedUsers } from '@/lib/event'
|
import { notificationFilter } from '@/lib/notification'
|
||||||
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
|
import { useContentPolicy } from '@/providers/ContentPolicyProvider'
|
||||||
import { useMuteList } from '@/providers/MuteListProvider'
|
import { useMuteList } from '@/providers/MuteListProvider'
|
||||||
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
|
import { useUserTrust } from '@/providers/UserTrustProvider'
|
||||||
import { Event, kinds } from 'nostr-tools'
|
import { Event, kinds } from 'nostr-tools'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { MentionNotification } from './MentionNotification'
|
import { MentionNotification } from './MentionNotification'
|
||||||
@@ -17,18 +19,26 @@ export function NotificationItem({
|
|||||||
notification: Event
|
notification: Event
|
||||||
isNew?: boolean
|
isNew?: boolean
|
||||||
}) {
|
}) {
|
||||||
|
const { pubkey } = useNostr()
|
||||||
const { mutePubkeySet } = useMuteList()
|
const { mutePubkeySet } = useMuteList()
|
||||||
const { hideContentMentioningMutedUsers } = useContentPolicy()
|
const { hideContentMentioningMutedUsers } = useContentPolicy()
|
||||||
const shouldHide = useMemo(() => {
|
const { hideUntrustedNotifications, isUserTrusted } = useUserTrust()
|
||||||
if (mutePubkeySet.has(notification.pubkey)) {
|
const canShow = useMemo(() => {
|
||||||
return true
|
return notificationFilter(notification, {
|
||||||
}
|
pubkey,
|
||||||
if (hideContentMentioningMutedUsers && isMentioningMutedUsers(notification, mutePubkeySet)) {
|
mutePubkeySet,
|
||||||
return true
|
hideContentMentioningMutedUsers,
|
||||||
}
|
hideUntrustedNotifications,
|
||||||
return false
|
isUserTrusted
|
||||||
}, [])
|
})
|
||||||
if (shouldHide) return null
|
}, [
|
||||||
|
notification,
|
||||||
|
mutePubkeySet,
|
||||||
|
hideContentMentioningMutedUsers,
|
||||||
|
hideUntrustedNotifications,
|
||||||
|
isUserTrusted
|
||||||
|
])
|
||||||
|
if (!canShow) return null
|
||||||
|
|
||||||
if (notification.kind === kinds.Reaction) {
|
if (notification.kind === kinds.Reaction) {
|
||||||
return <ReactionNotification notification={notification} isNew={isNew} />
|
return <ReactionNotification notification={notification} isNew={isNew} />
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { usePrimaryPage } from '@/PageManager'
|
|||||||
import { useNostr } from '@/providers/NostrProvider'
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
import { useNotification } from '@/providers/NotificationProvider'
|
import { useNotification } from '@/providers/NotificationProvider'
|
||||||
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
|
import { useUserPreferences } from '@/providers/UserPreferencesProvider'
|
||||||
import { useUserTrust } from '@/providers/UserTrustProvider'
|
|
||||||
import client from '@/services/client.service'
|
import client from '@/services/client.service'
|
||||||
import noteStatsService from '@/services/note-stats.service'
|
import noteStatsService from '@/services/note-stats.service'
|
||||||
import { TNotificationType } from '@/types'
|
import { TNotificationType } from '@/types'
|
||||||
@@ -33,7 +32,6 @@ const NotificationList = forwardRef((_, ref) => {
|
|||||||
const { current, display } = usePrimaryPage()
|
const { current, display } = usePrimaryPage()
|
||||||
const active = useMemo(() => current === 'notifications' && display, [current, display])
|
const active = useMemo(() => current === 'notifications' && display, [current, display])
|
||||||
const { pubkey } = useNostr()
|
const { pubkey } = useNostr()
|
||||||
const { hideUntrustedNotifications, isUserTrusted } = useUserTrust()
|
|
||||||
const { getNotificationsSeenAt } = useNotification()
|
const { getNotificationsSeenAt } = useNotification()
|
||||||
const { notificationListStyle } = useUserPreferences()
|
const { notificationListStyle } = useUserPreferences()
|
||||||
const [notificationType, setNotificationType] = useState<TNotificationType>('all')
|
const [notificationType, setNotificationType] = useState<TNotificationType>('all')
|
||||||
@@ -180,13 +178,8 @@ const NotificationList = forwardRef((_, ref) => {
|
|||||||
}, [pubkey, active, filterKinds, handleNewEvent])
|
}, [pubkey, active, filterKinds, handleNewEvent])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let visibleNotifications = notifications.slice(0, showCount)
|
setVisibleNotifications(notifications.slice(0, showCount))
|
||||||
if (hideUntrustedNotifications) {
|
}, [notifications, showCount])
|
||||||
visibleNotifications = visibleNotifications.filter((event) => isUserTrusted(event.pubkey))
|
|
||||||
}
|
|
||||||
|
|
||||||
setVisibleNotifications(visibleNotifications)
|
|
||||||
}, [notifications, showCount, hideUntrustedNotifications, isUserTrusted])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const options = {
|
const options = {
|
||||||
|
|||||||
35
src/lib/notification.ts
Normal file
35
src/lib/notification.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { kinds, NostrEvent } from 'nostr-tools'
|
||||||
|
import { isMentioningMutedUsers } from './event'
|
||||||
|
import { tagNameEquals } from './tag'
|
||||||
|
|
||||||
|
export function notificationFilter(
|
||||||
|
event: NostrEvent,
|
||||||
|
{
|
||||||
|
pubkey,
|
||||||
|
mutePubkeySet,
|
||||||
|
hideContentMentioningMutedUsers,
|
||||||
|
hideUntrustedNotifications,
|
||||||
|
isUserTrusted
|
||||||
|
}: {
|
||||||
|
pubkey?: string | null
|
||||||
|
mutePubkeySet: Set<string>
|
||||||
|
hideContentMentioningMutedUsers?: boolean
|
||||||
|
hideUntrustedNotifications?: boolean
|
||||||
|
isUserTrusted: (pubkey: string) => boolean
|
||||||
|
}
|
||||||
|
): boolean {
|
||||||
|
if (
|
||||||
|
mutePubkeySet.has(event.pubkey) ||
|
||||||
|
(hideContentMentioningMutedUsers && isMentioningMutedUsers(event, mutePubkeySet)) ||
|
||||||
|
(hideUntrustedNotifications && !isUserTrusted(event.pubkey))
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pubkey && event.kind === kinds.Reaction) {
|
||||||
|
const targetPubkey = event.tags.findLast(tagNameEquals('p'))?.[1]
|
||||||
|
if (targetPubkey !== pubkey) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
|
import { BIG_RELAY_URLS, ExtendedKind } from '@/constants'
|
||||||
import { compareEvents, isMentioningMutedUsers } from '@/lib/event'
|
import { compareEvents } from '@/lib/event'
|
||||||
|
import { notificationFilter } from '@/lib/notification'
|
||||||
import { usePrimaryPage } from '@/PageManager'
|
import { usePrimaryPage } from '@/PageManager'
|
||||||
import client from '@/services/client.service'
|
import client from '@/services/client.service'
|
||||||
import storage from '@/services/local-storage.service'
|
import storage from '@/services/local-storage.service'
|
||||||
@@ -47,9 +48,13 @@ export function NotificationProvider({ children }: { children: React.ReactNode }
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
mutePubkeySet.has(notification.pubkey) ||
|
!notificationFilter(notification, {
|
||||||
(hideContentMentioningMutedUsers && isMentioningMutedUsers(notification, mutePubkeySet)) ||
|
pubkey,
|
||||||
(hideUntrustedNotifications && !isUserTrusted(notification.pubkey))
|
mutePubkeySet,
|
||||||
|
hideContentMentioningMutedUsers,
|
||||||
|
hideUntrustedNotifications,
|
||||||
|
isUserTrusted
|
||||||
|
})
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user