diff --git a/src/components/Notes/NoteRender.tsx b/src/components/Notes/NoteRender.tsx index 5419f4d..fbe492a 100644 --- a/src/components/Notes/NoteRender.tsx +++ b/src/components/Notes/NoteRender.tsx @@ -6,6 +6,7 @@ import { Fragment } from 'react/jsx-runtime' import { BlogPreview } from './internal/BlogPreview' import { ModPreview } from './internal/ModPreview' import { NoteWrapper } from './internal/NoteWrapper' +import { NIP05_REGEX } from 'nostr-tools/nip05' interface NoteRenderProps { content: string @@ -16,13 +17,17 @@ const nostrMention = /(?:nostr:|@)?(?:npub|note|nprofile|nevent|naddr)1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{58,}/gi const nostrEntity = /(npub|note|nprofile|nevent|naddr)1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{58,}/gi +const nostrNip5Mention = /(?:nostr:|@)([^\s]{1,64}@[^\s]+\.[^\s]{2,})/gi export const NoteRender = ({ content }: NoteRenderProps) => { const _content = useMemo(() => { if (!content) return const parts = content.split( - new RegExp(`(${link.source})|(${nostrMention.source})`, 'gui') + new RegExp( + `(${link.source})|(${nostrMention.source})|${nostrNip5Mention.source}`, + 'gui' + ) ) const _parts = parts.map((part, index) => { @@ -63,6 +68,9 @@ export const NoteRender = ({ content }: NoteRenderProps) => { } catch (error) { return part } + } else if (NIP05_REGEX.test(part)) { + const [nip05] = part.match(NIP05_REGEX) || [] + return } else { return part } diff --git a/src/components/ProfileSection.tsx b/src/components/ProfileSection.tsx index d00d289..36d6b64 100644 --- a/src/components/ProfileSection.tsx +++ b/src/components/ProfileSection.tsx @@ -1,7 +1,7 @@ import { FALLBACK_PROFILE_IMAGE } from 'constants.ts' import { Event, Filter, kinds, nip19, UnsignedEvent } from 'nostr-tools' import { QRCodeSVG } from 'qrcode.react' -import { useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { Link } from 'react-router-dom' import { toast } from 'react-toastify' import { @@ -27,7 +27,11 @@ import { import { LoadingSpinner } from './LoadingSpinner' import { ZapPopUp } from './Zap' import placeholder from '../assets/img/DEGMods Placeholder Img.png' -import { NDKEvent, NDKSubscriptionCacheUsage } from '@nostr-dev-kit/ndk' +import { + NDKEvent, + NDKSubscriptionCacheUsage, + NDKUser +} from '@nostr-dev-kit/ndk' import { useProfile } from 'hooks/useProfile' import { createPortal } from 'react-dom' @@ -577,32 +581,52 @@ const FollowButton = ({ pubkey }: FollowButtonProps) => { ) } -export const ProfileLink = ({ pubkey }: Props) => { - let hexPubkey: string | null = null - let profileRoute: string | undefined = appRoutes.home - let nprofile: string | undefined - const npub = hexToNpub(pubkey) - - try { - hexPubkey = npubToHex(pubkey) - - if (hexPubkey) { - nprofile = hexPubkey - ? nip19.nprofileEncode({ - pubkey: hexPubkey - }) - : undefined - } - } catch (error) { - // Silently ignore - log(true, LogType.Error, 'Failed to encode profile.', error) - } - - profileRoute = nprofile ? getProfilePageRoute(nprofile) : appRoutes.home - const profile = useProfile(hexPubkey!, { +type ProfileLinkProps = { + pubkey?: string + nip05?: string +} +export const ProfileLink = ({ pubkey, nip05 }: ProfileLinkProps) => { + const { ndk } = useNDKContext() + console.log(`[debug]`, pubkey, nip05) + const [hexPubkey, setHexPubkey] = useState() + const profile = useProfile(hexPubkey, { cacheUsage: NDKSubscriptionCacheUsage.PARALLEL }) + useEffect(() => { + if (pubkey) { + setHexPubkey(pubkey) + } else if (nip05) { + NDKUser.fromNip05(nip05, ndk).then((user) => { + if (user?.pubkey) { + setHexPubkey(user.pubkey) + } + }) + } + }, [pubkey, nip05, ndk]) + + const profileRoute = useMemo(() => { + let nprofile: string | undefined + try { + if (hexPubkey) { + nprofile = hexPubkey + ? nip19.nprofileEncode({ + pubkey: hexPubkey + }) + : undefined + } + } catch (error) { + // Silently ignore + log(true, LogType.Error, 'Failed to encode profile.', error) + } + + return nprofile ? getProfilePageRoute(nprofile) : appRoutes.home + }, [hexPubkey]) + + const displayName = useMemo(() => { + const npub = hexPubkey ? hexToNpub(hexPubkey) : '' + const displayName = profile?.displayName || profile?.name || truncate(npub) + return displayName + }, [hexPubkey, profile?.displayName, profile?.name]) - const displayName = profile?.displayName || profile?.name || truncate(npub) return @{displayName} }