import { cardEventBodyBlurb } from '@/lib/card-event-body-blurb' import { getLongFormArticleMetadataFromEvent } from '@/lib/event-metadata' import { toNote, toNoteList } from '@/lib/link' import { useSecondaryPageOptional } from '@/PageManager' import { useShouldAutoLoadMedia } from '@/hooks/useShouldAutoLoadMedia' import { useScreenSizeOptional } from '@/providers/ScreenSizeProvider' import { cn } from '@/lib/utils' import { Event, kinds } from 'nostr-tools' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import ArticleCardCoverImage from './ArticleCardCoverImage' /** * Feed / embed / preview surface for NIP-23 long-form (kind 30023): title, summary, image, tags — no “Show more” body. * Full article stays on the note page ({@link showFull} on {@link Note}). */ export default function LongFormCard({ event, className, /** When false (e.g. parent-reply preview strip), card is non-interactive like the old one-line preview. */ interactive = true }: { event: Event className?: string interactive?: boolean }) { const { t } = useTranslation() const screenSize = useScreenSizeOptional() const isSmallScreen = screenSize?.isSmallScreen ?? false const secondaryPage = useSecondaryPageOptional() const push = secondaryPage?.push ?? ((url: string) => { window.location.href = url }) const autoLoadMedia = useShouldAutoLoadMedia(event.pubkey, event) const metadata = useMemo(() => getLongFormArticleMetadataFromEvent(event), [event]) const bodyBlurb = useMemo(() => cardEventBodyBlurb(event.content), [event.content]) const summaryText = (metadata.summary?.trim() || bodyBlurb).trim() const displayTitle = metadata.title?.trim() || t('Long-form Article') const handleCardClick = (e: React.MouseEvent) => { if (!interactive) return e.stopPropagation() push(toNote(event)) } const titleComponent = (
{displayTitle}
) const tagsComponent = interactive && metadata.tags.length > 0 && (
{metadata.tags.map((tag) => (
{ e.stopPropagation() push(toNoteList({ hashtag: tag, kinds: [kinds.LongFormArticle] })) }} > #{tag}
))}
) const tagsReadonly = !interactive && metadata.tags.length > 0 && (
{metadata.tags.map((tag) => ( #{tag} ))}
) const summaryComponent = summaryText ? (
{summaryText}
) : null const shellClass = cn(className, !interactive && 'pointer-events-none') const cardClass = cn( 'rounded-lg border p-4 transition-colors', interactive && 'cursor-pointer hover:bg-muted/50' ) if (isSmallScreen) { return (
{titleComponent} {summaryComponent} {tagsComponent} {tagsReadonly}
) } return (
{titleComponent} {summaryComponent} {tagsComponent} {tagsReadonly}
) }