import React, { useState } from 'react'; import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import IconButton from '@mui/material/IconButton'; import Tooltip from '@mui/material/Tooltip'; import Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'; import DownloadIcon from '@mui/icons-material/Download'; import CloseIcon from '@mui/icons-material/Close'; interface FileParam { name: string; size?: number; mimetype?: string; id: number | string; path?: string; previewAvailable?: string; } interface FileMessageContentProps { messageParameters: Record; isOwnMessage: boolean; } function formatFileSize(bytes?: number): string { if (!bytes) return ''; if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } function extractFileParams(messageParameters: Record): FileParam[] { const files: FileParam[] = []; for (const key of Object.keys(messageParameters)) { if (key === 'file' || key.startsWith('file')) { const val = messageParameters[key]; if (val && typeof val === 'object' && val.id) { files.push(val as FileParam); } } } return files; } type OverlayMode = 'image' | 'pdf' | 'video'; interface ContentOverlayProps { open: boolean; onClose: () => void; mode: OverlayMode; contentUrl: string; downloadUrl: string; name: string; } const ContentOverlay: React.FC = ({ open, onClose, mode, contentUrl, downloadUrl, name }) => ( {mode === 'image' && ( )} {mode === 'pdf' && ( )} {mode === 'video' && ( )} {name} ); const FileMessageContent: React.FC = ({ messageParameters, isOwnMessage }) => { const [overlayFile, setOverlayFile] = useState<{ file: FileParam; mode: OverlayMode } | null>(null); const files = extractFileParams(messageParameters); if (files.length === 0) return null; const getOverlayMode = (file: FileParam): OverlayMode | null => { const mime = file.mimetype ?? ''; if (mime.startsWith('image/') && file.previewAvailable === 'yes') return 'image'; if (mime === 'application/pdf') return 'pdf'; if (mime.startsWith('video/')) return 'video'; return null; }; return ( <> {files.map((file, idx) => { const downloadUrl = `/api/nextcloud/talk/files/${file.id}/download${file.path ? `?path=${encodeURIComponent(file.path)}` : ''}`; const thumbUrl = `/api/nextcloud/talk/files/${file.id}/preview?w=400&h=400`; const mime = file.mimetype ?? ''; const isImage = mime.startsWith('image/') && file.previewAvailable === 'yes'; const isAudio = mime.startsWith('audio/'); const overlayMode = getOverlayMode(file); if (isImage) { return ( setOverlayFile({ file, mode: 'image' })} sx={{ maxWidth: '100%', maxHeight: 200, borderRadius: 1, display: 'block', cursor: 'zoom-in', '&:hover': { opacity: 0.9 }, }} /> {file.name} ); } if (isAudio) { return ( {file.name} ); } return ( { if (overlayMode) { setOverlayFile({ file, mode: overlayMode }); } else { window.open(downloadUrl, '_blank', 'noopener,noreferrer'); } }} sx={{ mt: 0.5, display: 'flex', alignItems: 'center', gap: 1, p: 0.75, borderRadius: 1, cursor: 'pointer', bgcolor: isOwnMessage ? 'rgba(255,255,255,0.15)' : (theme: any) => theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)', '&:hover': { bgcolor: isOwnMessage ? 'rgba(255,255,255,0.25)' : (theme: any) => theme.palette.mode === 'dark' ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)', }, }} > {file.name} {file.size && ( {formatFileSize(file.size)} )} e.stopPropagation()} sx={{ flexShrink: 0, color: 'inherit' }} > ); })} {overlayFile && ( setOverlayFile(null)} mode={overlayFile.mode} contentUrl={ overlayFile.mode === 'image' ? `/api/nextcloud/talk/files/${overlayFile.file.id}/preview?w=1200&h=1200` : `/api/nextcloud/talk/files/${overlayFile.file.id}/download${overlayFile.file.path ? `?path=${encodeURIComponent(overlayFile.file.path)}` : ''}` } downloadUrl={`/api/nextcloud/talk/files/${overlayFile.file.id}/download${overlayFile.file.path ? `?path=${encodeURIComponent(overlayFile.file.path)}` : ''}`} name={overlayFile.file.name} /> )} ); }; export default FileMessageContent;