// Primus IQ — File View Modal (inline preview + details + actions) const FileViewModal = ({ file, onClose, onDownload }) => { const [viewUrl, setViewUrl] = React.useState(null); const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(''); // Fetch an inline (preview) signed URL when a file is opened. React.useEffect(() => { if (!file) return; setViewUrl(null); setError(''); setLoading(true); // 'pending-*' ids are client-side placeholders for a queued import, not real // artifact UUIDs — don't fetch a preview URL that can't exist yet. if (String(file.id || '').startsWith('pending')) { setLoading(false); setError('This file is still being imported — the preview will be available once it finishes.'); return; } PrimusAPI.getViewUrl(file.id) .then(r => setViewUrl(typeof r === 'string' ? r : (r.download_url || r.url))) .catch(ex => setError(ex.status === 403 ? 'You do not have permission to view this file.' : (ex.message || 'Could not load the preview.'))) .finally(() => setLoading(false)); }, [file && file.id]); // Esc to close React.useEffect(() => { if (!file) return; const onKey = (e) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [file]); if (!file) return null; const ext = (file.ext || '').toLowerCase(); const isImage = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg'].includes(ext); const isPdf = ext === 'pdf'; const canPreview = isImage || isPdf; const meta = [ext ? ext.toUpperCase() : null, file.size, file.added || file.modified].filter(Boolean).join(' · '); return (