You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

60 lines
1.7 KiB

import { useFetchEvent } from '@/hooks'
import CitationCard from '@/components/CitationCard'
import { Skeleton } from '@/components/ui/skeleton'
import { nip19 } from 'nostr-tools'
interface EmbeddedCitationProps {
citationId: string // nevent or note ID
displayType?: 'end' | 'foot' | 'foot-end' | 'inline' | 'quote' | 'prompt-end' | 'prompt-inline'
className?: string
}
export default function EmbeddedCitation({ citationId, displayType = 'end', className }: EmbeddedCitationProps) {
// Strip all nostr: prefixes if present (handle cases like nostr:nostr:nevent1...)
let cleanId = citationId.trim()
while (cleanId.startsWith('nostr:')) {
cleanId = cleanId.substring(6) // Remove 'nostr:' prefix
}
// Try to decode as bech32 first
let eventId: string | null = null
try {
const decoded = nip19.decode(cleanId)
if (decoded.type === 'nevent') {
const data = decoded.data as any
eventId = data.id || cleanId
} else if (decoded.type === 'note') {
eventId = decoded.data as string
} else {
// If it's not a note/nevent, use the original ID
eventId = cleanId
}
} catch {
// If decoding fails, assume it's already a hex ID
eventId = cleanId
}
const { event, isFetching } = useFetchEvent(eventId || '')
if (isFetching) {
return (
<div className={className}>
<Skeleton className="h-24 w-full" />
</div>
)
}
if (!event) {
return (
<div className={className}>
<div className="text-sm text-muted-foreground p-2 border rounded">
Citation not found: {citationId.slice(0, 20)}...
</div>
</div>
)
}
return <CitationCard event={event} displayType={displayType} className={className} />
}