diff --git a/src/components/NostrMentionLink.tsx b/src/components/NostrMentionLink.tsx index 6b507028..ca16fc5f 100644 --- a/src/components/NostrMentionLink.tsx +++ b/src/components/NostrMentionLink.tsx @@ -18,93 +18,29 @@ const NostrMentionLink: React.FC = ({ onClick, className = 'highlight-comment-link' }) => { + // Decode the nostr URI first + let decoded: ReturnType | null = null + let pubkey: string | undefined + try { - // Remove nostr: prefix const identifier = nostrUri.replace(/^nostr:/, '') - const decoded = nip19.decode(identifier) + decoded = nip19.decode(identifier) - switch (decoded.type) { - case 'npub': { - const pubkey = decoded.data - // Fetch profile in the background - const profile = useEventModel(Models.ProfileModel, [pubkey]) - const displayName = profile?.name || profile?.display_name || profile?.nip05 || `${pubkey.slice(0, 8)}...` - - return ( - - @{displayName} - - ) - } - case 'nprofile': { - const { pubkey } = decoded.data - // Fetch profile in the background - const profile = useEventModel(Models.ProfileModel, [pubkey]) - const displayName = profile?.name || profile?.display_name || profile?.nip05 || `${pubkey.slice(0, 8)}...` - const npub = nip19.npubEncode(pubkey) - - return ( - - @{displayName} - - ) - } - case 'naddr': { - const { kind, pubkey, identifier: addrIdentifier } = decoded.data - // Check if it's a blog post (kind:30023) - if (kind === 30023) { - const naddr = nip19.naddrEncode({ kind, pubkey, identifier: addrIdentifier }) - return ( - - {addrIdentifier || 'Article'} - - ) - } - // For other kinds, show shortened identifier - return ( - - nostr:{addrIdentifier.slice(0, 12)}... - - ) - } - case 'note': { - const eventId = decoded.data - return ( - - note:{eventId.slice(0, 12)}... - - ) - } - case 'nevent': { - const { id } = decoded.data - return ( - - event:{id.slice(0, 12)}... - - ) - } - default: - // Fallback for unrecognized types - return ( - - {identifier.slice(0, 20)}... - - ) + // Extract pubkey for profile fetching (works for npub and nprofile) + if (decoded.type === 'npub') { + pubkey = decoded.data + } else if (decoded.type === 'nprofile') { + pubkey = decoded.data.pubkey } } catch (error) { - // If decoding fails, show shortened identifier + // Decoding failed, will fallback to shortened identifier + } + + // Fetch profile at top level (Rules of Hooks) + const profile = useEventModel(Models.ProfileModel, pubkey ? [pubkey] : null) + + // If decoding failed, show shortened identifier + if (!decoded) { const identifier = nostrUri.replace(/^nostr:/, '') return ( @@ -112,6 +48,86 @@ const NostrMentionLink: React.FC = ({ ) } + + // Render based on decoded type + switch (decoded.type) { + case 'npub': { + const pk = decoded.data + const displayName = profile?.name || profile?.display_name || profile?.nip05 || `${pk.slice(0, 8)}...` + + return ( + + @{displayName} + + ) + } + case 'nprofile': { + const { pubkey: pk } = decoded.data + const displayName = profile?.name || profile?.display_name || profile?.nip05 || `${pk.slice(0, 8)}...` + const npub = nip19.npubEncode(pk) + + return ( + + @{displayName} + + ) + } + case 'naddr': { + const { kind, pubkey: pk, identifier: addrIdentifier } = decoded.data + // Check if it's a blog post (kind:30023) + if (kind === 30023) { + const naddr = nip19.naddrEncode({ kind, pubkey: pk, identifier: addrIdentifier }) + return ( + + {addrIdentifier || 'Article'} + + ) + } + // For other kinds, show shortened identifier + return ( + + nostr:{addrIdentifier.slice(0, 12)}... + + ) + } + case 'note': { + const eventId = decoded.data + return ( + + note:{eventId.slice(0, 12)}... + + ) + } + case 'nevent': { + const { id } = decoded.data + return ( + + event:{id.slice(0, 12)}... + + ) + } + default: { + // Fallback for unrecognized types + const identifier = nostrUri.replace(/^nostr:/, '') + return ( + + {identifier.slice(0, 20)}... + + ) + } + } } export default NostrMentionLink