mirror of
https://github.com/dergigi/boris.git
synced 2025-12-18 15:14:20 +01:00
refactor: clean up npub/nprofile display implementation
- Remove all debug console.log/error statements (39+) and ts() helpers - Eliminate redundant localStorage cache check in useProfileLabels - Standardize fallback display format using getNpubFallbackDisplay() utility - Update ResolvedMention to use npub format consistently
This commit is contained in:
@@ -3,6 +3,7 @@ import { Link } from 'react-router-dom'
|
|||||||
import { useEventModel } from 'applesauce-react/hooks'
|
import { useEventModel } from 'applesauce-react/hooks'
|
||||||
import { Models, Helpers } from 'applesauce-core'
|
import { Models, Helpers } from 'applesauce-core'
|
||||||
import { decode, npubEncode } from 'nostr-tools/nip19'
|
import { decode, npubEncode } from 'nostr-tools/nip19'
|
||||||
|
import { getNpubFallbackDisplay } from '../utils/nostrUriResolver'
|
||||||
|
|
||||||
const { getPubkeyFromDecodeResult } = Helpers
|
const { getPubkeyFromDecodeResult } = Helpers
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ const ResolvedMention: React.FC<ResolvedMentionProps> = ({ encoded }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const profile = pubkey ? useEventModel(Models.ProfileModel, [pubkey]) : undefined
|
const profile = pubkey ? useEventModel(Models.ProfileModel, [pubkey]) : undefined
|
||||||
const display = profile?.name || profile?.display_name || profile?.nip05 || (pubkey ? `${pubkey.slice(0, 8)}...` : encoded)
|
const display = profile?.name || profile?.display_name || profile?.nip05 || (pubkey ? getNpubFallbackDisplay(pubkey) : encoded)
|
||||||
const npub = pubkey ? npubEncode(pubkey) : undefined
|
const npub = pubkey ? npubEncode(pubkey) : undefined
|
||||||
|
|
||||||
if (npub) {
|
if (npub) {
|
||||||
|
|||||||
@@ -4,13 +4,6 @@ import { extractNaddrUris, replaceNostrUrisInMarkdownWithProfileLabels } from '.
|
|||||||
import { fetchArticleTitles } from '../services/articleTitleResolver'
|
import { fetchArticleTitles } from '../services/articleTitleResolver'
|
||||||
import { useProfileLabels } from './useProfileLabels'
|
import { useProfileLabels } from './useProfileLabels'
|
||||||
|
|
||||||
// Helper to add timestamps to logs
|
|
||||||
const ts = () => {
|
|
||||||
const now = new Date()
|
|
||||||
const ms = now.getMilliseconds().toString().padStart(3, '0')
|
|
||||||
return `${now.toLocaleTimeString('en-US', { hour12: false })}.${ms}`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook to convert markdown to HTML using a hidden ReactMarkdown component
|
* Hook to convert markdown to HTML using a hidden ReactMarkdown component
|
||||||
* Also processes nostr: URIs in the markdown and resolves article titles
|
* Also processes nostr: URIs in the markdown and resolves article titles
|
||||||
@@ -31,11 +24,6 @@ export const useMarkdownToHTML = (
|
|||||||
// Resolve profile labels progressively as profiles load
|
// Resolve profile labels progressively as profiles load
|
||||||
const profileLabels = useProfileLabels(markdown || '', relayPool)
|
const profileLabels = useProfileLabels(markdown || '', relayPool)
|
||||||
|
|
||||||
// Log when markdown or profile labels change (but throttle excessive logs)
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(`[${ts()}] [npub-resolve] useMarkdownToHTML: markdown length:`, markdown?.length || 0, 'hasRelayPool:', !!relayPool, 'Profile labels size:', profileLabels.size)
|
|
||||||
}, [markdown?.length, profileLabels.size, relayPool])
|
|
||||||
|
|
||||||
// Fetch article titles
|
// Fetch article titles
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!markdown || !relayPool) {
|
if (!markdown || !relayPool) {
|
||||||
@@ -57,8 +45,7 @@ export const useMarkdownToHTML = (
|
|||||||
if (!isCancelled) {
|
if (!isCancelled) {
|
||||||
setArticleTitles(titlesMap)
|
setArticleTitles(titlesMap)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch {
|
||||||
console.warn('Failed to fetch article titles:', error)
|
|
||||||
if (!isCancelled) setArticleTitles(new Map())
|
if (!isCancelled) setArticleTitles(new Map())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -80,8 +67,6 @@ export const useMarkdownToHTML = (
|
|||||||
let isCancelled = false
|
let isCancelled = false
|
||||||
|
|
||||||
const processMarkdown = () => {
|
const processMarkdown = () => {
|
||||||
console.log(`[${ts()}] [npub-resolve] useMarkdownToHTML: Processing markdown, length:`, markdown.length)
|
|
||||||
console.log(`[${ts()}] [npub-resolve] useMarkdownToHTML: Profile labels:`, profileLabels.size, 'Article titles:', articleTitles.size)
|
|
||||||
try {
|
try {
|
||||||
// Replace nostr URIs with profile labels (progressive) and article titles
|
// Replace nostr URIs with profile labels (progressive) and article titles
|
||||||
const processed = replaceNostrUrisInMarkdownWithProfileLabels(
|
const processed = replaceNostrUrisInMarkdownWithProfileLabels(
|
||||||
@@ -89,13 +74,11 @@ export const useMarkdownToHTML = (
|
|||||||
profileLabels,
|
profileLabels,
|
||||||
articleTitles
|
articleTitles
|
||||||
)
|
)
|
||||||
console.log(`[${ts()}] [npub-resolve] useMarkdownToHTML: Processed markdown length:`, processed.length)
|
|
||||||
|
|
||||||
if (isCancelled) return
|
if (isCancelled) return
|
||||||
|
|
||||||
setProcessedMarkdown(processed)
|
setProcessedMarkdown(processed)
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.error(`[${ts()}] [npub-resolve] useMarkdownToHTML: Error processing markdown:`, err)
|
|
||||||
if (!isCancelled) {
|
if (!isCancelled) {
|
||||||
setProcessedMarkdown(markdown) // Fallback to original
|
setProcessedMarkdown(markdown) // Fallback to original
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMemo, useState, useEffect, useRef } from 'react'
|
import { useMemo, useState, useEffect } from 'react'
|
||||||
import { Hooks } from 'applesauce-react'
|
import { Hooks } from 'applesauce-react'
|
||||||
import { Helpers, IEventStore } from 'applesauce-core'
|
import { Helpers, IEventStore } from 'applesauce-core'
|
||||||
import { getContentPointers } from 'applesauce-factory/helpers'
|
import { getContentPointers } from 'applesauce-factory/helpers'
|
||||||
@@ -7,13 +7,6 @@ import { fetchProfiles, loadCachedProfiles } from '../services/profileService'
|
|||||||
|
|
||||||
const { getPubkeyFromDecodeResult, encodeDecodeResult } = Helpers
|
const { getPubkeyFromDecodeResult, encodeDecodeResult } = Helpers
|
||||||
|
|
||||||
// Helper to add timestamps to logs
|
|
||||||
const ts = () => {
|
|
||||||
const now = new Date()
|
|
||||||
const ms = now.getMilliseconds().toString().padStart(3, '0')
|
|
||||||
return `${now.toLocaleTimeString('en-US', { hour12: false })}.${ms}`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook to resolve profile labels from content containing npub/nprofile identifiers
|
* Hook to resolve profile labels from content containing npub/nprofile identifiers
|
||||||
* Returns a Map of encoded identifier -> display name that updates progressively as profiles load
|
* Returns a Map of encoded identifier -> display name that updates progressively as profiles load
|
||||||
@@ -23,12 +16,9 @@ export function useProfileLabels(content: string, relayPool?: RelayPool | null):
|
|||||||
|
|
||||||
// Extract profile pointers (npub and nprofile) using applesauce helpers
|
// Extract profile pointers (npub and nprofile) using applesauce helpers
|
||||||
const profileData = useMemo(() => {
|
const profileData = useMemo(() => {
|
||||||
console.log(`[${ts()}] [npub-resolve] Processing content, length:`, content?.length || 0)
|
|
||||||
try {
|
try {
|
||||||
const pointers = getContentPointers(content)
|
const pointers = getContentPointers(content)
|
||||||
console.log(`[${ts()}] [npub-resolve] Found pointers:`, pointers.length, 'types:', pointers.map(p => p.type))
|
|
||||||
const filtered = pointers.filter(p => p.type === 'npub' || p.type === 'nprofile')
|
const filtered = pointers.filter(p => p.type === 'npub' || p.type === 'nprofile')
|
||||||
console.log(`[${ts()}] [npub-resolve] Profile pointers:`, filtered.length)
|
|
||||||
const result: Array<{ pubkey: string; encoded: string }> = []
|
const result: Array<{ pubkey: string; encoded: string }> = []
|
||||||
filtered.forEach(pointer => {
|
filtered.forEach(pointer => {
|
||||||
try {
|
try {
|
||||||
@@ -37,14 +27,12 @@ export function useProfileLabels(content: string, relayPool?: RelayPool | null):
|
|||||||
if (pubkey && encoded) {
|
if (pubkey && encoded) {
|
||||||
result.push({ pubkey, encoded: encoded as string })
|
result.push({ pubkey, encoded: encoded as string })
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.error(`[${ts()}] [npub-resolve] Error processing pointer:`, err, pointer)
|
// Ignore errors, continue processing other pointers
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(`[${ts()}] [npub-resolve] Profile data after filtering:`, result.length)
|
|
||||||
return result
|
return result
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.error(`[${ts()}] [npub-resolve] Error extracting pointers:`, err)
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}, [content])
|
}, [content])
|
||||||
@@ -74,53 +62,31 @@ export function useProfileLabels(content: string, relayPool?: RelayPool | null):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (labels.size > 0) {
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Initial labels from cache (useMemo):`, labels.size, 'labels')
|
|
||||||
}
|
|
||||||
return labels
|
return labels
|
||||||
}, [profileData])
|
}, [profileData])
|
||||||
|
|
||||||
const [profileLabels, setProfileLabels] = useState<Map<string, string>>(initialLabels)
|
const [profileLabels, setProfileLabels] = useState<Map<string, string>>(initialLabels)
|
||||||
const lastLoggedSize = useRef<number>(0)
|
|
||||||
|
|
||||||
// Build initial labels: localStorage cache -> eventStore -> fetch from relays
|
// Build initial labels: localStorage cache -> eventStore -> fetch from relays
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const startTime = Date.now()
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Building labels, profileData:`, profileData.length, 'hasEventStore:', !!eventStore, 'hasRelayPool:', !!relayPool)
|
|
||||||
|
|
||||||
// Extract all pubkeys
|
// Extract all pubkeys
|
||||||
const allPubkeys = profileData.map(({ pubkey }) => pubkey)
|
const allPubkeys = profileData.map(({ pubkey }) => pubkey)
|
||||||
|
|
||||||
if (allPubkeys.length === 0) {
|
if (allPubkeys.length === 0) {
|
||||||
console.log(`[${ts()}] [npub-resolve] No pubkeys to resolve, clearing labels`)
|
|
||||||
setProfileLabels(new Map())
|
setProfileLabels(new Map())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, check localStorage cache (synchronous, instant)
|
|
||||||
const cacheStartTime = Date.now()
|
|
||||||
const cachedProfiles = loadCachedProfiles(allPubkeys)
|
|
||||||
const cacheDuration = Date.now() - cacheStartTime
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Found in localStorage cache:`, cachedProfiles.size, 'out of', allPubkeys.length, 'in', cacheDuration, 'ms')
|
|
||||||
|
|
||||||
// Log which pubkeys were found in cache
|
|
||||||
if (cachedProfiles.size > 0) {
|
|
||||||
cachedProfiles.forEach((_profile, pubkey) => {
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Cached profile found:`, pubkey.slice(0, 16) + '...')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add cached profiles to EventStore for consistency
|
// Add cached profiles to EventStore for consistency
|
||||||
|
const cachedProfiles = loadCachedProfiles(allPubkeys)
|
||||||
if (eventStore) {
|
if (eventStore) {
|
||||||
for (const profile of cachedProfiles.values()) {
|
for (const profile of cachedProfiles.values()) {
|
||||||
eventStore.add(profile)
|
eventStore.add(profile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build labels from localStorage cache and eventStore (initialLabels already has cache, add eventStore)
|
// Build labels from localStorage cache and eventStore
|
||||||
// Start with labels from initial cache lookup (in useMemo)
|
// initialLabels already has all cached profiles, so we only need to check eventStore
|
||||||
// Note: initialLabels should already have all cached profiles, but we rebuild here
|
|
||||||
// to also check EventStore and handle any profiles that weren't in cache
|
|
||||||
const labels = new Map<string, string>(initialLabels)
|
const labels = new Map<string, string>(initialLabels)
|
||||||
|
|
||||||
const pubkeysToFetch: string[] = []
|
const pubkeysToFetch: string[] = []
|
||||||
@@ -131,20 +97,12 @@ export function useProfileLabels(content: string, relayPool?: RelayPool | null):
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check EventStore for profiles that weren't in cache
|
||||||
let profileEvent: { content: string } | null = null
|
let profileEvent: { content: string } | null = null
|
||||||
let foundSource = ''
|
if (eventStore) {
|
||||||
|
|
||||||
// Check localStorage cache first (should already be checked in initialLabels, but double-check)
|
|
||||||
const cachedProfile = cachedProfiles.get(pubkey)
|
|
||||||
if (cachedProfile) {
|
|
||||||
profileEvent = cachedProfile
|
|
||||||
foundSource = 'localStorage cache'
|
|
||||||
} else if (eventStore) {
|
|
||||||
// Then check EventStore (in-memory from current session)
|
|
||||||
const eventStoreProfile = eventStore.getEvent(pubkey + ':0')
|
const eventStoreProfile = eventStore.getEvent(pubkey + ':0')
|
||||||
if (eventStoreProfile) {
|
if (eventStoreProfile) {
|
||||||
profileEvent = eventStoreProfile
|
profileEvent = eventStoreProfile
|
||||||
foundSource = 'eventStore'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,13 +112,10 @@ export function useProfileLabels(content: string, relayPool?: RelayPool | null):
|
|||||||
const displayName = profileData.display_name || profileData.name || profileData.nip05
|
const displayName = profileData.display_name || profileData.name || profileData.nip05
|
||||||
if (displayName) {
|
if (displayName) {
|
||||||
labels.set(encoded, `@${displayName}`)
|
labels.set(encoded, `@${displayName}`)
|
||||||
console.log(`[${ts()}] [npub-resolve] Found in ${foundSource}:`, encoded.slice(0, 30) + '...', '->', displayName)
|
|
||||||
} else {
|
} else {
|
||||||
console.log(`[${ts()}] [npub-resolve] Profile from ${foundSource} has no display name, will fetch:`, pubkey.slice(0, 16) + '...')
|
|
||||||
pubkeysToFetch.push(pubkey)
|
pubkeysToFetch.push(pubkey)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.error(`[${ts()}] [npub-resolve] Error parsing profile from ${foundSource}:`, err)
|
|
||||||
pubkeysToFetch.push(pubkey)
|
pubkeysToFetch.push(pubkey)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -168,99 +123,55 @@ export function useProfileLabels(content: string, relayPool?: RelayPool | null):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Update labels with what we found in localStorage cache and eventStore
|
|
||||||
const initialResolveTime = Date.now() - startTime
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Initial resolution complete:`, labels.size, 'labels resolved in', initialResolveTime, 'ms. Will fetch', pubkeysToFetch.length, 'missing profiles.')
|
|
||||||
setProfileLabels(new Map(labels))
|
setProfileLabels(new Map(labels))
|
||||||
|
|
||||||
// Fetch missing profiles asynchronously
|
// Fetch missing profiles asynchronously
|
||||||
if (pubkeysToFetch.length > 0 && relayPool && eventStore) {
|
if (pubkeysToFetch.length > 0 && relayPool && eventStore) {
|
||||||
const fetchStartTime = Date.now()
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Fetching`, pubkeysToFetch.length, 'missing profiles')
|
|
||||||
fetchProfiles(relayPool, eventStore as unknown as IEventStore, pubkeysToFetch)
|
fetchProfiles(relayPool, eventStore as unknown as IEventStore, pubkeysToFetch)
|
||||||
.then((fetchedProfiles) => {
|
.then((fetchedProfiles) => {
|
||||||
const fetchDuration = Date.now() - fetchStartTime
|
|
||||||
console.log(`[${ts()}] [npub-resolve] fetchProfiles returned`, fetchedProfiles.length, 'profiles in', fetchDuration, 'ms')
|
|
||||||
|
|
||||||
// First, use the profiles returned from fetchProfiles directly
|
|
||||||
const updatedLabels = new Map(labels)
|
const updatedLabels = new Map(labels)
|
||||||
const fetchedProfilesByPubkey = new Map(fetchedProfiles.map(p => [p.pubkey, p]))
|
const fetchedProfilesByPubkey = new Map(fetchedProfiles.map(p => [p.pubkey, p]))
|
||||||
|
|
||||||
let resolvedFromArray = 0
|
|
||||||
let resolvedFromStore = 0
|
|
||||||
let withNames = 0
|
|
||||||
let withoutNames = 0
|
|
||||||
let missingFromStore = 0
|
|
||||||
|
|
||||||
profileData.forEach(({ encoded, pubkey }) => {
|
profileData.forEach(({ encoded, pubkey }) => {
|
||||||
if (!updatedLabels.has(encoded)) {
|
if (!updatedLabels.has(encoded)) {
|
||||||
// First, try to use the profile from the returned array
|
// First, try to use the profile from the returned array
|
||||||
const fetchedProfile = fetchedProfilesByPubkey.get(pubkey)
|
const fetchedProfile = fetchedProfilesByPubkey.get(pubkey)
|
||||||
if (fetchedProfile) {
|
if (fetchedProfile) {
|
||||||
resolvedFromArray++
|
|
||||||
try {
|
try {
|
||||||
const profileData = JSON.parse(fetchedProfile.content || '{}') as { name?: string; display_name?: string; nip05?: string }
|
const profileData = JSON.parse(fetchedProfile.content || '{}') as { name?: string; display_name?: string; nip05?: string }
|
||||||
const displayName = profileData.display_name || profileData.name || profileData.nip05
|
const displayName = profileData.display_name || profileData.name || profileData.nip05
|
||||||
if (displayName) {
|
if (displayName) {
|
||||||
updatedLabels.set(encoded, `@${displayName}`)
|
updatedLabels.set(encoded, `@${displayName}`)
|
||||||
withNames++
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Resolved from fetched array:`, encoded.slice(0, 30) + '...', '->', displayName)
|
|
||||||
} else {
|
|
||||||
withoutNames++
|
|
||||||
if (withoutNames <= 3) {
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Fetched profile has no name/display_name/nip05:`, encoded.slice(0, 30) + '...', 'content keys:', Object.keys(profileData))
|
|
||||||
}
|
}
|
||||||
}
|
} catch {
|
||||||
} catch (err) {
|
// Ignore parsing errors
|
||||||
console.error(`[${ts()}] [npub-resolve] Error parsing fetched profile for`, encoded.slice(0, 30) + '...', err)
|
|
||||||
}
|
}
|
||||||
} else if (eventStore) {
|
} else if (eventStore) {
|
||||||
// Fallback: check eventStore (in case fetchProfiles stored but didn't return)
|
// Fallback: check eventStore (in case fetchProfiles stored but didn't return)
|
||||||
const profileEvent = eventStore.getEvent(pubkey + ':0')
|
const profileEvent = eventStore.getEvent(pubkey + ':0')
|
||||||
if (profileEvent) {
|
if (profileEvent) {
|
||||||
resolvedFromStore++
|
|
||||||
try {
|
try {
|
||||||
const profileData = JSON.parse(profileEvent.content || '{}') as { name?: string; display_name?: string; nip05?: string }
|
const profileData = JSON.parse(profileEvent.content || '{}') as { name?: string; display_name?: string; nip05?: string }
|
||||||
const displayName = profileData.display_name || profileData.name || profileData.nip05
|
const displayName = profileData.display_name || profileData.name || profileData.nip05
|
||||||
if (displayName) {
|
if (displayName) {
|
||||||
updatedLabels.set(encoded, `@${displayName}`)
|
updatedLabels.set(encoded, `@${displayName}`)
|
||||||
withNames++
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Resolved from eventStore:`, encoded.slice(0, 30) + '...', '->', displayName)
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.error(`[${ts()}] [npub-resolve] Error parsing profile event for`, encoded.slice(0, 30) + '...', err)
|
// Ignore parsing errors
|
||||||
}
|
|
||||||
} else {
|
|
||||||
missingFromStore++
|
|
||||||
if (missingFromStore <= 3) {
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Profile not found in array or eventStore:`, pubkey.slice(0, 16) + '...')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
missingFromStore++
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const totalDuration = Date.now() - startTime
|
|
||||||
console.log(`[${ts()}] [npub-resolve] After fetch - resolved:`, updatedLabels.size, 'total | from array:', resolvedFromArray, '| from store:', resolvedFromStore, '| with names:', withNames, '| without names:', withoutNames, '| missing:', missingFromStore, '| out of', profileData.length, '| total time:', totalDuration, 'ms')
|
|
||||||
setProfileLabels(updatedLabels)
|
setProfileLabels(updatedLabels)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(() => {
|
||||||
const fetchDuration = Date.now() - fetchStartTime
|
// Silently handle fetch errors
|
||||||
console.error(`[${ts()}] [npub-resolve] Error fetching profiles after`, fetchDuration, 'ms:', err)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [profileData, eventStore, relayPool, initialLabels])
|
}, [profileData, eventStore, relayPool, initialLabels])
|
||||||
|
|
||||||
// Only log when size actually changes to reduce noise
|
|
||||||
useEffect(() => {
|
|
||||||
if (profileLabels.size !== lastLoggedSize.current) {
|
|
||||||
console.log(`[${ts()}] [npub-resolve] Final labels map size:`, profileLabels.size)
|
|
||||||
lastLoggedSize.current = profileLabels.size
|
|
||||||
}
|
|
||||||
}, [profileLabels.size])
|
|
||||||
|
|
||||||
return profileLabels
|
return profileLabels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,6 @@ import { Tokens } from 'applesauce-content/helpers'
|
|||||||
import { getContentPointers } from 'applesauce-factory/helpers'
|
import { getContentPointers } from 'applesauce-factory/helpers'
|
||||||
import { encodeDecodeResult } from 'applesauce-core/helpers'
|
import { encodeDecodeResult } from 'applesauce-core/helpers'
|
||||||
|
|
||||||
// Helper to add timestamps to logs
|
|
||||||
const ts = () => {
|
|
||||||
const now = new Date()
|
|
||||||
const ms = now.getMilliseconds().toString().padStart(3, '0')
|
|
||||||
return `${now.toLocaleTimeString('en-US', { hour12: false })}.${ms}`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Regular expression to match nostr: URIs and bare NIP-19 identifiers
|
* Regular expression to match nostr: URIs and bare NIP-19 identifiers
|
||||||
* Uses applesauce Tokens.nostrLink which includes word boundary checks
|
* Uses applesauce Tokens.nostrLink which includes word boundary checks
|
||||||
@@ -23,10 +16,8 @@ const NOSTR_URI_REGEX = Tokens.nostrLink
|
|||||||
* Extract all nostr URIs from text using applesauce helpers
|
* Extract all nostr URIs from text using applesauce helpers
|
||||||
*/
|
*/
|
||||||
export function extractNostrUris(text: string): string[] {
|
export function extractNostrUris(text: string): string[] {
|
||||||
console.log(`[${ts()}] [npub-resolve] extractNostrUris: text length:`, text?.length || 0)
|
|
||||||
try {
|
try {
|
||||||
const pointers = getContentPointers(text)
|
const pointers = getContentPointers(text)
|
||||||
console.log(`[${ts()}] [npub-resolve] extractNostrUris: Found pointers:`, pointers.length)
|
|
||||||
const result: string[] = []
|
const result: string[] = []
|
||||||
pointers.forEach(pointer => {
|
pointers.forEach(pointer => {
|
||||||
try {
|
try {
|
||||||
@@ -34,14 +25,12 @@ export function extractNostrUris(text: string): string[] {
|
|||||||
if (encoded) {
|
if (encoded) {
|
||||||
result.push(encoded)
|
result.push(encoded)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.error(`[${ts()}] [npub-resolve] extractNostrUris: Error encoding pointer:`, err, pointer)
|
// Ignore encoding errors, continue processing other pointers
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(`[${ts()}] [npub-resolve] extractNostrUris: Extracted URIs:`, result.length)
|
|
||||||
return result
|
return result
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.error(`[${ts()}] [npub-resolve] extractNostrUris: Error:`, err)
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,6 +117,23 @@ export function getNostrUriLabel(encoded: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a standardized fallback display name for a pubkey when profile has no name
|
||||||
|
* Returns npub format: @abc1234...
|
||||||
|
* @param pubkey The pubkey in hex format
|
||||||
|
* @returns Formatted npub display string
|
||||||
|
*/
|
||||||
|
export function getNpubFallbackDisplay(pubkey: string): string {
|
||||||
|
try {
|
||||||
|
const npub = npubEncode(pubkey)
|
||||||
|
// Remove "npub1" prefix (5 chars) and show next 7 chars
|
||||||
|
return `@${npub.slice(5, 12)}...`
|
||||||
|
} catch {
|
||||||
|
// Fallback to shortened pubkey if encoding fails
|
||||||
|
return `@${pubkey.slice(0, 8)}...`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process markdown to replace nostr URIs while skipping those inside markdown links
|
* Process markdown to replace nostr URIs while skipping those inside markdown links
|
||||||
* This prevents nested markdown link issues when nostr identifiers appear in URLs
|
* This prevents nested markdown link issues when nostr identifiers appear in URLs
|
||||||
|
|||||||
Reference in New Issue
Block a user