diff --git a/src/components/Bookmarks.tsx b/src/components/Bookmarks.tsx index 194179ec..279aaaa6 100644 --- a/src/components/Bookmarks.tsx +++ b/src/components/Bookmarks.tsx @@ -2,8 +2,11 @@ import React, { useMemo, useEffect, useRef } from 'react' import { useParams, useLocation, useNavigate } from 'react-router-dom' import { Hooks } from 'applesauce-react' import { useEventStore } from 'applesauce-react/hooks' +import { Helpers } from 'applesauce-core' import { RelayPool } from 'applesauce-relay' import { nip19 } from 'nostr-tools' + +const { getPubkeyFromDecodeResult } = Helpers import { useSettings } from '../hooks/useSettings' import { useArticleLoader } from '../hooks/useArticleLoader' import { useExternalUrlLoader } from '../hooks/useExternalUrlLoader' @@ -79,16 +82,12 @@ const Bookmarks: React.FC = ({ // Extract tab from profile routes const profileTab = location.pathname.endsWith('/writings') ? 'writings' : 'highlights' - // Decode npub or nprofile to pubkey for profile view + // Decode npub or nprofile to pubkey for profile view using applesauce helper let profilePubkey: string | undefined if (npub && showProfile) { try { const decoded = nip19.decode(npub) - if (decoded.type === 'npub') { - profilePubkey = decoded.data - } else if (decoded.type === 'nprofile') { - profilePubkey = decoded.data.pubkey - } + profilePubkey = getPubkeyFromDecodeResult(decoded) } catch (err) { console.error('Failed to decode npub/nprofile:', err) } diff --git a/src/components/NostrMentionLink.tsx b/src/components/NostrMentionLink.tsx index ea03e5bd..2fe2623f 100644 --- a/src/components/NostrMentionLink.tsx +++ b/src/components/NostrMentionLink.tsx @@ -47,8 +47,8 @@ const NostrMentionLink: React.FC = ({ }, [pubkey, eventStore]) // Show loading if profile doesn't exist and not in cache/store (for npub/nprofile) - const isLoading = !profile && pubkey && !isInCacheOrStore && - decoded && (decoded.type === 'npub' || decoded.type === 'nprofile') + // pubkey will be undefined for non-profile types, so no need for explicit type check + const isLoading = !profile && pubkey && !isInCacheOrStore // If decoding failed, show shortened identifier if (!decoded) { @@ -78,15 +78,12 @@ const NostrMentionLink: React.FC = ({ } // Render based on decoded type + // If we have a pubkey (from npub/nprofile), render profile link directly + if (pubkey) { + return renderProfileLink(pubkey) + } + switch (decoded.type) { - case 'npub': { - const pk = decoded.data - return renderProfileLink(pk) - } - case 'nprofile': { - const { pubkey: pk } = decoded.data - return renderProfileLink(pk) - } case 'naddr': { const { kind, pubkey: pk, identifier: addrIdentifier } = decoded.data // Check if it's a blog post (kind:30023) diff --git a/src/utils/nostrUriResolver.tsx b/src/utils/nostrUriResolver.tsx index 778cb24e..20e7d1c8 100644 --- a/src/utils/nostrUriResolver.tsx +++ b/src/utils/nostrUriResolver.tsx @@ -2,7 +2,9 @@ import { decode, npubEncode, noteEncode } from 'nostr-tools/nip19' import { getNostrUrl } from '../config/nostrGateways' import { Tokens } from 'applesauce-content/helpers' import { getContentPointers } from 'applesauce-factory/helpers' -import { encodeDecodeResult } from 'applesauce-core/helpers' +import { encodeDecodeResult, Helpers } from 'applesauce-core/helpers' + +const { getPubkeyFromDecodeResult } = Helpers /** * Regular expression to match nostr: URIs and bare NIP-19 identifiers @@ -85,17 +87,14 @@ export function getNostrUriLabel(encoded: string): string { try { const decoded = decode(encoded) + // Use applesauce helper to extract pubkey for npub/nprofile + const pubkey = getPubkeyFromDecodeResult(decoded) + if (pubkey) { + // Use shared fallback display function and add @ for label + return `@${getNpubFallbackDisplay(pubkey)}` + } + switch (decoded.type) { - case 'npub': { - // Use shared fallback display function and add @ for label - const pubkey = decoded.data - return `@${getNpubFallbackDisplay(pubkey)}` - } - case 'nprofile': { - // Use shared fallback display function and add @ for label - const pubkey = decoded.data.pubkey - return `@${getNpubFallbackDisplay(pubkey)}` - } case 'note': return `note:${encoded.slice(5, 12)}...` case 'nevent': { @@ -334,10 +333,9 @@ export function replaceNostrUrisInMarkdownWithProfileLabels( return `[${title}](${link})` } - // For npub/nprofile, extract pubkey and use it as the lookup key - if (decoded.type === 'npub' || decoded.type === 'nprofile') { - const pubkey = decoded.type === 'npub' ? decoded.data : decoded.data.pubkey - + // For npub/nprofile, extract pubkey using applesauce helper + const pubkey = getPubkeyFromDecodeResult(decoded) + if (pubkey) { // Check if we have a resolved profile name using pubkey as key // Use the label if: 1) we have a label, AND 2) profile is not currently loading (false or undefined) const isLoading = profileLoading.get(pubkey) @@ -383,15 +381,9 @@ export function addLoadingClassToProfileLinks( // Find all tags with href starting with /p/ (profile links) const result = html.replace(/]*?href="\/p\/([^"]+)"[^>]*?>/g, (match, npub: string) => { try { - // Decode npub or nprofile to get pubkey + // Decode npub or nprofile to get pubkey using applesauce helper const decoded: ReturnType = decode(npub) - - let pubkey: string | undefined - if (decoded.type === 'npub') { - pubkey = decoded.data - } else if (decoded.type === 'nprofile') { - pubkey = decoded.data.pubkey - } + const pubkey = getPubkeyFromDecodeResult(decoded) if (pubkey) { // Check if this profile is loading