mirror of
https://github.com/dergigi/boris.git
synced 2025-12-18 15:14:20 +01:00
feat(/e/): title 'Note by @author' with background profile fetch
- Immediate fallback title using short pubkey - Fetch kind:0 profile in background; update title when available - Keeps UI responsive while improving attribution
This commit is contained in:
@@ -4,6 +4,7 @@ import { IEventStore } from 'applesauce-core'
|
|||||||
import { NostrEvent } from 'nostr-tools'
|
import { NostrEvent } from 'nostr-tools'
|
||||||
import { ReadableContent } from '../services/readerService'
|
import { ReadableContent } from '../services/readerService'
|
||||||
import { eventManager } from '../services/eventManager'
|
import { eventManager } from '../services/eventManager'
|
||||||
|
import { fetchProfiles } from '../services/profileService'
|
||||||
|
|
||||||
interface UseEventLoaderProps {
|
interface UseEventLoaderProps {
|
||||||
eventId?: string
|
eventId?: string
|
||||||
@@ -39,13 +40,43 @@ export function useEventLoader({
|
|||||||
.replace(/>/g, '>')
|
.replace(/>/g, '>')
|
||||||
.replace(/\n/g, '<br />')
|
.replace(/\n/g, '<br />')
|
||||||
|
|
||||||
const content: ReadableContent = {
|
// Initial title
|
||||||
url: '', // Empty URL to prevent highlight display
|
let title = `Note (${event.kind})`
|
||||||
html: metaHtml + `<div style="white-space: pre-wrap; word-break: break-word;">${escapedContent}</div>`,
|
if (event.kind === 1) {
|
||||||
title: `Note (${event.kind})`
|
title = `Note by @${event.pubkey.slice(0, 8)}...`
|
||||||
}
|
}
|
||||||
setReaderContent(content)
|
|
||||||
}, [setReaderContent])
|
// Emit immediately
|
||||||
|
const baseContent: ReadableContent = {
|
||||||
|
url: '',
|
||||||
|
html: metaHtml + `<div style="white-space: pre-wrap; word-break: break-word;">${escapedContent}</div>`,
|
||||||
|
title
|
||||||
|
}
|
||||||
|
setReaderContent(baseContent)
|
||||||
|
|
||||||
|
// Background: resolve author profile for kind:1 and update title
|
||||||
|
if (event.kind === 1 && relayPool && eventStore) {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const profiles = await fetchProfiles(relayPool, eventStore as unknown as IEventStore, [event.pubkey])
|
||||||
|
if (!profiles || profiles.length === 0) return
|
||||||
|
const latest = profiles.sort((a, b) => (b.created_at || 0) - (a.created_at || 0))[0]
|
||||||
|
let resolved = ''
|
||||||
|
try {
|
||||||
|
const obj = JSON.parse(latest.content || '{}') as { name?: string; display_name?: string; nip05?: string }
|
||||||
|
resolved = obj.display_name || obj.name || obj.nip05 || ''
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
if (resolved) {
|
||||||
|
setReaderContent({ ...baseContent, title: `Note by @${resolved}` })
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// ignore profile failures; keep fallback title
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
}, [setReaderContent, relayPool, eventStore])
|
||||||
|
|
||||||
// Initialize event manager with services
|
// Initialize event manager with services
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -57,7 +88,7 @@ export function useEventLoader({
|
|||||||
|
|
||||||
setReaderLoading(true)
|
setReaderLoading(true)
|
||||||
setReaderContent(undefined)
|
setReaderContent(undefined)
|
||||||
setSelectedUrl('') // Don't set nostr: URL to avoid showing highlights
|
setSelectedUrl(`nostr-event:${eventId}`) // sentinel: truthy selection, not treated as article
|
||||||
setIsCollapsed(false)
|
setIsCollapsed(false)
|
||||||
|
|
||||||
// Fetch using event manager (handles cache, deduplication, and retry)
|
// Fetch using event manager (handles cache, deduplication, and retry)
|
||||||
|
|||||||
Reference in New Issue
Block a user