From e175f77f8d45534944c571f48d991dac7cdbb219 Mon Sep 17 00:00:00 2001 From: hasak21 Date: Thu, 3 Sep 2026 17:39:32 +0800 Subject: [PATCH] fix(components): preserve download dialog for HTML attachments (#321) Clicking an HTML file attachment uploaded via lody_upload_files with a workspace sourcePath previously short-circuited handlePreview into the live file viewer or browser connection, completely skipping SessionFilePreviewDialog. Because SessionFileCard has no separate download button, users had no way to download the attached HTML file bytes. Retain the in-app preview dialog for HTML attachments so that Download and Copy actions remain accessible. Add onOpenLivePreview to SessionFilePreviewDialog to provide a dedicated action to open the live preview when live provenance is present, and wire canOpenHtmlFile so the action is only shown when available. Model: gemini-3.8-flash --- locales/en.json | 1 + locales/zh_CN.json | 1 + .../src/components/ai-gui/index.tsx | 4 + .../ai-gui/session-file-preview-dialog.tsx | 34 +++- .../ai-gui/session-files-rendering.md | 8 +- .../components/src/components/ai-gui/view.tsx | 23 ++- .../sessions/session-chat-interface.tsx | 20 +++ .../session-file-preview-dialog.test.tsx | 156 ++++++++++++++++++ 8 files changed, 234 insertions(+), 13 deletions(-) create mode 100644 packages/components/tests/session-file-preview-dialog.test.tsx diff --git a/locales/en.json b/locales/en.json index 73bc12f40..7dba4f568 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1961,6 +1961,7 @@ "sessions.imageStoredAsLocalFile": "Image upload is offline; added as a pending file attachment.", "sessions.fileDownload": "Download", "sessions.fileDownloadFull": "Download full file", + "sessions.openLivePreview": "Open live preview", "sessions.filePreviewRendered": "Rendered", "sessions.filePreviewRaw": "Raw", "sessions.filePreviewTruncated": "Preview shows only the start of this file. Download the full file to see everything.", diff --git a/locales/zh_CN.json b/locales/zh_CN.json index 8eb5cc241..c1b215ad1 100644 --- a/locales/zh_CN.json +++ b/locales/zh_CN.json @@ -1961,6 +1961,7 @@ "sessions.imageStoredAsLocalFile": "图片上传处于离线状态,已作为待同步文件附件添加。", "sessions.fileDownload": "下载", "sessions.fileDownloadFull": "下载完整文件", + "sessions.openLivePreview": "打开实时预览", "sessions.filePreviewRendered": "渲染", "sessions.filePreviewRaw": "原文", "sessions.filePreviewTruncated": "预览仅显示文件开头部分。下载完整文件以查看全部内容。", diff --git a/packages/components/src/components/ai-gui/index.tsx b/packages/components/src/components/ai-gui/index.tsx index 1cdf37e9c..2bf512c52 100644 --- a/packages/components/src/components/ai-gui/index.tsx +++ b/packages/components/src/components/ai-gui/index.tsx @@ -89,6 +89,8 @@ export interface SessionChatStreamProps { onFilePathClick?: (filePath: string) => void; /** Routes HTML attachment clicks to a live file or Browser surface. */ onOpenHtmlFile?: (file: SessionFilePayload) => boolean; + /** Whether an HTML attachment can be routed to a live file or Browser surface. */ + canOpenHtmlFile?: (file: SessionFilePayload) => boolean; messageFileDiffEntriesByTurn?: MessageFileDiffEntriesByTurn; assistantActions?: AssistantMessageAction[]; assistantActionsMessageId?: string | null; @@ -171,6 +173,7 @@ const SessionChatStreamImpl = forwardRef void; isDownloading?: boolean; + onOpenLivePreview?: (file: SessionFilePayload) => void; }; /** @@ -38,6 +39,7 @@ export function SessionFilePreviewPanel({ status, onDownload, isDownloading = false, + onOpenLivePreview, }: SessionFilePreviewPanelProps) { const { t } = useTranslation(); const markdown = isMarkdownFile(file.fileName); @@ -123,7 +125,20 @@ export function SessionFilePreviewPanel({ )} - {/* Divider separates content actions (copy/download) from the window + {onOpenLivePreview ? ( + + ) : null} + {/* Divider separates content actions (copy/download/live-preview) from the window action (close), and the close sits inline in the same row instead of floating in the corner over the buttons. */}