import React, { useState } from 'react' import { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl' import MediaPlayer, { type MediaPlayerProps } from './MediaPlayer' import { renderTypeIcon } from './utils/icons' import { getSourceType } from './utils/mimeType' export type AttachmentThumbnailVariant = 'light' | 'dark' export interface AttachmentThumbnailProps { mimeType: string sourceUrl?: string thumbnailUrl?: string title?: string variant: AttachmentThumbnailVariant /** Extra props passed to MediaPlayer when source is video or audio. */ mediaPlayerProps?: Partial< Pick< MediaPlayerProps, 'autoPlay' | 'loop' | 'muted' | 'controls' | 'onContainerClick' > > /** * When true (Visitor unlocked image/document), use aspect-video + object-contain fade-in. */ containedImage?: boolean } const placeholderIconClass = (variant: AttachmentThumbnailVariant) => variant === 'dark' ? 'size-12 text-white/20' : 'size-12 text-black/20' const posterShellClass = (variant: AttachmentThumbnailVariant) => variant === 'dark' ? 'aspect-video overflow-hidden bg-white/10' : 'aspect-video overflow-hidden bg-black/5' /** * Renders the media preview area for attachment cards (LockedAttachment, MediaMessage). * Overlays (dim, lock, eye toggle) are composed by the parent. */ const AttachmentThumbnail: React.FC = ({ mimeType, sourceUrl, thumbnailUrl, title, variant, mediaPlayerProps, containedImage = false, }) => { const sourceType = getSourceType(mimeType) const [sourceReady, setSourceReady] = useState(false) const optimizedSourceUrl = optimizeMessagingAttachmentUrl(sourceUrl) const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl) if (sourceUrl && (sourceType === 'video' || sourceType === 'audio')) { return ( ) } if (sourceUrl && sourceType === 'image') { if (containedImage) { return (
{title setSourceReady(true)} />
) } return ( {title ) } if (sourceUrl && sourceType === 'document') { if (thumbnailUrl) { if (containedImage) { return (
{title setSourceReady(true)} />
) } return ( ) } return (
{renderTypeIcon(mimeType, { className: placeholderIconClass(variant), weight: 'regular', })}
) } // Poster-only or empty (no sourceUrl) if (thumbnailUrl) { return (
{title
) } return (
{renderTypeIcon(mimeType, { className: placeholderIconClass(variant), weight: 'regular', })}
) } export default AttachmentThumbnail