import { ExtendedKind } from '@/constants' import { getPublicationIndexMetadataFromEvent, type PublicationAuthor } from '@/lib/event-metadata' import { toNoteList } from '@/lib/link' import { cn } from '@/lib/utils' import { useSecondaryPageOptional } from '@/PageManager' import { useShouldAutoLoadMedia } from '@/hooks/useShouldAutoLoadMedia' import { BookOpen, ExternalLink } from 'lucide-react' import { Event, kinds } from 'nostr-tools' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import PublicationCoverFallback from './PublicationCoverFallback' import PublicationCoverImage from './PublicationCoverImage' import PublicationBooklistButton from './PublicationBooklistButton' function formatAuthorLine(authors: PublicationAuthor[]): string { if (authors.length === 0) return '' return authors .map(({ name, role }) => { const normalizedRole = role?.trim().toLowerCase() if (!normalizedRole || normalizedRole === 'author') return name return `${name} (${role})` }) .join(' ยท ') } function formatPublicationType(type: string): string { return type .split(/[\s_-]+/) .filter(Boolean) .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()) .join(' ') } function sourceHostname(source: string): string { try { return new URL(source).hostname.replace(/^www\./, '') } catch { return source } } function MetaChip({ children, className }: { children: React.ReactNode; className?: string }) { return ( {children} ) } export default function PublicationIndexMetadata({ event, variant = 'compact', showTitle = true, className }: { event: Event variant?: 'compact' | 'full' showTitle?: boolean className?: string }) { const { t } = useTranslation() const secondaryPage = useSecondaryPageOptional() const push = secondaryPage?.push ?? ((url: string) => { window.location.href = url }) const autoLoadMedia = useShouldAutoLoadMedia(event.pubkey, event) const metadata = useMemo(() => getPublicationIndexMetadataFromEvent(event), [event]) if (event.kind !== ExtendedKind.PUBLICATION) return null const authorLine = formatAuthorLine(metadata.authors) const isFull = variant === 'full' const title = metadata.title?.trim() || event.tags.find((tag) => tag[0] === 'd')?.[1]?.replace(/-/g, ' ') || t('Publication Note') const metaChips: React.ReactNode[] = [] if (metadata.type) { metaChips.push({formatPublicationType(metadata.type)}) } if (metadata.language) { metaChips.push({metadata.language.toUpperCase()}) } if (metadata.version) { metaChips.push({t('Publication version', { version: metadata.version })}) } if (metadata.sectionCount > 0) { metaChips.push( {t('Publication sections', { count: metadata.sectionCount })} ) } const tagsComponent = metadata.tags.length > 0 ? (
{metadata.tags.map((tag) => ( ))}
) : null return (
{isFull && metadata.image?.trim() ? ( ) : isFull ? ( ) : null} {showTitle ? (
{title}
) : null} {authorLine ? (
{authorLine}
) : null} {metaChips.length > 0 ? (
{metaChips}
) : null} {metadata.releaseDate ? (
{t('Publication released', { date: metadata.releaseDate })}
) : null} {metadata.summary ? (
{metadata.summary}
) : null} {metadata.source || tagsComponent || isFull ? (
{metadata.source ? ( e.stopPropagation()} > {sourceHostname(metadata.source)} ) : null} {tagsComponent} {isFull ? : null}
) : null} {isFull && metadata.sections.length > 0 ? (
{t('Publication table of contents')}
    {metadata.sections.map((section, index) => (
  1. {index + 1}. {section.label || section.coordinate.split(':').pop()?.replace(/-/g, ' ') || section.coordinate}
  2. ))}
) : null}
) }