From f3e2c3f58de61c7d58bb3689e9df9f46a1d87b29 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Fri, 27 Mar 2026 08:26:44 +0100 Subject: [PATCH] inlcude kind 16 reposts --- src/components/ContentPreview/index.tsx | 4 +- src/components/KindFilter/index.tsx | 2 +- .../LatestFromFollowsSection/index.tsx | 3 +- src/components/Note/NotificationEventCard.tsx | 5 ++- src/components/Note/index.tsx | 10 ++++- src/components/NoteBoostBadges/index.tsx | 2 +- src/components/NoteCard/RepostNoteCard.tsx | 39 +++++++++++++------ src/components/NoteCard/index.tsx | 6 +-- src/components/NoteStats/SeenOnButton.tsx | 22 +++++++++-- src/components/Profile/ProfileFeed.tsx | 3 +- .../Profile/ProfileFeedWithPins.tsx | 9 ++++- src/constants.ts | 9 ++++- src/lib/draft-event.ts | 9 ++++- src/lib/event.ts | 24 +++++++----- src/lib/kind-description.ts | 2 + src/pages/primary/SpellsPage/index.tsx | 6 ++- src/pages/secondary/NotePage/index.tsx | 1 + src/providers/NostrProvider/index.tsx | 2 +- src/services/client-events.service.ts | 2 +- src/services/client-query.service.ts | 12 ++++-- src/services/client.service.ts | 25 +++++++++--- src/services/nip89.service.ts | 1 + src/services/note-stats.service.ts | 35 ++++++++++++++--- 23 files changed, 172 insertions(+), 61 deletions(-) diff --git a/src/components/ContentPreview/index.tsx b/src/components/ContentPreview/index.tsx index 97544862..2d06c1f2 100644 --- a/src/components/ContentPreview/index.tsx +++ b/src/components/ContentPreview/index.tsx @@ -4,7 +4,7 @@ import { notificationReactionSummaryKey, useNotificationReactionDisplay } from '@/hooks/useNotificationReactionDisplay' -import { isMentioningMutedUsers, isNip25ReactionKind } from '@/lib/event' +import { isMentioningMutedUsers, isNip18RepostKind, isNip25ReactionKind } from '@/lib/event' import { DISCUSSION_DOWNVOTE_DISPLAY, DISCUSSION_UPVOTE_DISPLAY @@ -204,7 +204,7 @@ export default function ContentPreview({ ) } - if (event.kind === kinds.Repost) { + if (isNip18RepostKind(event.kind)) { return withKindRow(
{t('Notification boost summary')}
) diff --git a/src/components/KindFilter/index.tsx b/src/components/KindFilter/index.tsx index cd52d4d3..fa497518 100644 --- a/src/components/KindFilter/index.tsx +++ b/src/components/KindFilter/index.tsx @@ -27,7 +27,7 @@ const KIND_FILTER_OPTIONS = [ { kindGroup: [ExtendedKind.DISCUSSION], label: 'Discussions' }, { kindGroup: [ExtendedKind.CALENDAR_EVENT_DATE, ExtendedKind.CALENDAR_EVENT_TIME], label: 'Calendar Events' }, { kindGroup: [ExtendedKind.ZAP_RECEIPT], label: 'Zaps' }, - { kindGroup: [kinds.Repost], label: 'Boosts' } + { kindGroup: [kinds.Repost, ExtendedKind.GENERIC_REPOST], label: 'Boosts' } ] function buildShowKindsFromOptions( diff --git a/src/components/LatestFromFollowsSection/index.tsx b/src/components/LatestFromFollowsSection/index.tsx index d1a832ec..923337fc 100644 --- a/src/components/LatestFromFollowsSection/index.tsx +++ b/src/components/LatestFromFollowsSection/index.tsx @@ -54,7 +54,8 @@ const FEED_KINDS = [ ExtendedKind.VIDEO, ExtendedKind.SHORT_VIDEO, ExtendedKind.COMMENT, - kinds.Repost + kinds.Repost, + ExtendedKind.GENERIC_REPOST ] as number[] const feedKindSet = new Set(FEED_KINDS) diff --git a/src/components/Note/NotificationEventCard.tsx b/src/components/Note/NotificationEventCard.tsx index 35278cde..a4e1ef2a 100644 --- a/src/components/Note/NotificationEventCard.tsx +++ b/src/components/Note/NotificationEventCard.tsx @@ -1,6 +1,7 @@ import { ExtendedKind } from '@/constants' +import { isNip18RepostKind } from '@/lib/event' import { cn } from '@/lib/utils' -import { Event, kinds } from 'nostr-tools' +import { Event } from 'nostr-tools' import { useTranslation } from 'react-i18next' /** @@ -10,7 +11,7 @@ import { useTranslation } from 'react-i18next' export default function NotificationEventCard({ event, className }: { event: Event; className?: string }) { const { t } = useTranslation() - if (event.kind === kinds.Repost) { + if (isNip18RepostKind(event.kind)) { return (
setShowNsfw(true)} /> } else if (isNip25ReactionKind(event.kind)) { content = null - } else if (event.kind === kinds.Repost || event.kind === ExtendedKind.POLL_RESPONSE) { + } else if (isNip18RepostKind(event.kind) || event.kind === ExtendedKind.POLL_RESPONSE) { content = } else if (event.kind === kinds.Highlights) { // Try to render the Highlight component with error boundary diff --git a/src/components/NoteBoostBadges/index.tsx b/src/components/NoteBoostBadges/index.tsx index c99e4f3c..4f3482c9 100644 --- a/src/components/NoteBoostBadges/index.tsx +++ b/src/components/NoteBoostBadges/index.tsx @@ -11,7 +11,7 @@ import UserAvatar from '../UserAvatar' const MAX_VISIBLE = 28 /** - * Small avatar strip of users who boosted (kind 6) the note — shown under the OP on the note page. + * Small avatar strip of users who boosted (kind 6 / 16) the note — shown under the OP on the note page. */ export default function NoteBoostBadges({ event, className }: { event: Event; className?: string }) { const { t } = useTranslation() diff --git a/src/components/NoteCard/RepostNoteCard.tsx b/src/components/NoteCard/RepostNoteCard.tsx index 661731a5..12c8cbab 100644 --- a/src/components/NoteCard/RepostNoteCard.tsx +++ b/src/components/NoteCard/RepostNoteCard.tsx @@ -1,5 +1,6 @@ +import { ExtendedKind } from '@/constants' import { isMentioningMutedUsers } from '@/lib/event' -import { tagNameEquals } from '@/lib/tag' +import { generateBech32IdFromATag, getFirstHexEventIdFromETags, tagNameEquals } from '@/lib/tag' import { useContentPolicy } from '@/providers/ContentPolicyProvider' import { useMuteList } from '@/contexts/mute-list-context' import client from '@/services/client.service' @@ -37,7 +38,7 @@ export default function RepostNoteCard({ try { const eventFromContent = event.content ? (JSON.parse(event.content) as Event) : null if (eventFromContent && verifyEvent(eventFromContent)) { - if (eventFromContent.kind === kinds.Repost) { + if (eventFromContent.kind === kinds.Repost || eventFromContent.kind === ExtendedKind.GENERIC_REPOST) { return } client.addEventToCache(eventFromContent) @@ -52,18 +53,32 @@ export default function RepostNoteCard({ return } - const [, id, relay, , pubkey] = event.tags.find(tagNameEquals('e')) ?? [] - if (!id) { + const hex = getFirstHexEventIdFromETags(event.tags) + if (hex) { + const row = + event.tags.find((t) => (t[0] === 'e' || t[0] === 'E') && t[1] === hex) ?? [] + const [, id, relay, , pubkey] = row + const targetEventId = nip19.neventEncode({ + id, + relays: relay ? [relay] : [], + author: pubkey + }) + const targetEvent = await eventService.fetchEvent(targetEventId) + if (targetEvent) { + setTargetEvent(targetEvent) + } return } - const targetEventId = nip19.neventEncode({ - id, - relays: relay ? [relay] : [], - author: pubkey - }) - const targetEvent = await eventService.fetchEvent(targetEventId) - if (targetEvent) { - setTargetEvent(targetEvent) + + if (event.kind === ExtendedKind.GENERIC_REPOST) { + const aRow = event.tags.find(tagNameEquals('a')) ?? event.tags.find(tagNameEquals('A')) + const naddr = aRow ? generateBech32IdFromATag(aRow) : undefined + if (naddr) { + const ev = await eventService.fetchEvent(naddr) + if (ev) { + setTargetEvent(ev) + } + } } } catch { // ignore diff --git a/src/components/NoteCard/index.tsx b/src/components/NoteCard/index.tsx index abdd4d5f..60bf055a 100644 --- a/src/components/NoteCard/index.tsx +++ b/src/components/NoteCard/index.tsx @@ -1,8 +1,8 @@ import { Skeleton } from '@/components/ui/skeleton' -import { isMentioningMutedUsers } from '@/lib/event' +import { isMentioningMutedUsers, isNip18RepostKind } from '@/lib/event' import { useContentPolicy } from '@/providers/ContentPolicyProvider' import { useMuteList } from '@/contexts/mute-list-context' -import { Event, kinds } from 'nostr-tools' +import { Event } from 'nostr-tools' import { memo, useMemo } from 'react' import MainNoteCard from './MainNoteCard' import RepostNoteCard from './RepostNoteCard' @@ -36,7 +36,7 @@ const NoteCard = memo(function NoteCard({ }, [event, filterMutedNotes, mutePubkeySet]) if (shouldHide) return null - if (event.kind === kinds.Repost) { + if (isNip18RepostKind(event.kind)) { return ( { - const seenOn = client.getSeenEventRelayUrls(event.id) - setRelays(seenOn) - }, []) + let cancelled = false + let attempts = 0 + const maxAttempts = 20 + const apply = () => { + const seenOn = client.getSeenEventRelayUrls(event.id) + if (!cancelled) setRelays(seenOn) + return seenOn.length > 0 + } + if (apply()) return + const id = setInterval(() => { + if (cancelled) return + attempts++ + if (apply() || attempts >= maxAttempts) clearInterval(id) + }, 500) + return () => { + cancelled = true + clearInterval(id) + } + }, [event.id]) const trigger = (