Chuyển tới nội dung chính

File Viewer

FileViewer là modal dùng chung để xem tất cả loại file — từ attachment trong user message, workspace file trong AI message, đến file trong WorkingFolderPanel sidebar.


Entry Points

NguồnTriggerComponent
User message attachmentClick AttachmentChip trong message bubblehandleAttachmentClick() → ChatApp root modal
AI message file (FilesBlock)Click FileCard trong attachments blockFileViewer mở từ FilesBlock
Workspace sidebarClick file trong WorkingFolderPanelFileViewer mở từ panel

Props

interface FileViewerProps {
file: {
path: string; // Đường dẫn file trong workspace
filename: string; // Tên hiển thị
icon_type: string; // 'pdf', 'md', 'xlsx', 'csv', 'zip', 'image', 'json', 'txt', 'code'
source?: string; // 'generated' | 'upload'
};
sessionId: string; // Dùng để gọi content API
onClose: () => void;
}

Content Loading

FileViewer gọi API để lấy nội dung file khi mở:

GET /v2/sessions/{session_id}/files/content?file_path={path}
Authorization: Bearer {token}

Response text file:

{
"content": "# Báo cáo\n\nNội dung...",
"filename": "report.md",
"file_path": "/report.md",
"download_url": null
}

Response binary file:

{
"content": null,
"filename": "report.pdf",
"file_path": "/report.pdf",
"download_url": "https://s3.amazonaws.com/...?X-Amz-Expires=3600..."
}

Render Theo Loại File

icon_typeRendererChi tiết
pdf<iframe>Embed PDF với native browser controls
image, png, jpg, gif, webp<img>Centered, max-height 60vh, giữ aspect ratio
mdReactMarkdown + proseGFM, tables, code blocks có copy button
xlsx, xls, csvSpreadsheetRendererExcel viewer, cell selection, sheet tabs
zipZipViewerArchive viewer, list files bên trong
json, txt, code, py, js, v.v.<pre><code>Monospace, whitespace preserved
UnsupportedPlaceholderIcon + message + download button

Tính Năng

Download

  • Binary file (pdf, xlsx...): Tải thẳng từ download_url
  • Text file (md, txt...): Tải nội dung dưới dạng raw file

Convert (Markdown only)

Khi file là .md, có dropdown menu chuyển đổi:

POST /v2/sessions/{session_id}/files/convert
Authorization: Bearer {token}
Content-Type: application/json

{
"file_path": "/report.md",
"convert_type": "pdf"
}
convert_typeOutput
"md"Download raw markdown
"pdf"Chuyển thành PDF (có CSS styling)
"docx"Chuyển thành Word Document

Response:

{
"download_url": "https://s3.amazonaws.com/converted/...?expires=3600",
"filename": "report.pdf"
}

Download URL có hạn 1 giờ.

Expand / Collapse

  • Default: w-[1200px] h-[85vh]
  • Expanded: w-screen h-screen
  • Toggle qua nút expand ở header

Keyboard

  • Escape → đóng modal
  • Backdrop click → đóng modal

Animation

  • Mở: zoom-in + backdrop fade-in
  • Đóng: zoom-out + backdrop fade-out

Ví Dụ: Mở FileViewer

function FileCard({ file, sessionId }) {
const [viewerOpen, setViewerOpen] = useState(false);

return (
<>
<div onClick={() => setViewerOpen(true)}>
{file.filename}
</div>
{viewerOpen && (
<FileViewer
file={file}
sessionId={sessionId}
onClose={() => setViewerOpen(false)}
/>
)}
</>
);
}

Ví Dụ: Flutter

Flutter không dùng inline viewer — mở link download trong browser hoặc dùng native PDF viewer:

Future<void> openFile(String sessionId, String filePath, String iconType) async {
final res = await authorizedGet(
'/v2/sessions/$sessionId/files/content?file_path=${Uri.encodeComponent(filePath)}'
);
final data = jsonDecode(res.body);

if (data['content'] != null) {
// Text file — hiển thị trong in-app viewer
Navigator.push(context, MaterialPageRoute(
builder: (_) => TextFileViewer(content: data['content'], filename: data['filename']),
));
} else if (data['download_url'] != null) {
// Binary — mở URL trong browser
await launchUrl(Uri.parse(data['download_url']));
}
}

Future<void> convertAndDownload(String sessionId, String filePath, String convertType) async {
final res = await authorizedPost(
'/v2/sessions/$sessionId/files/convert',
body: {'file_path': filePath, 'convert_type': convertType},
);
final data = jsonDecode(res.body);
await launchUrl(Uri.parse(data['download_url']));
}