feat(web-shell): preview uploaded images in the right panel - #8930
Conversation
Click an image in a user message or a pasted image in the composer to open it in the right-hand artifact panel as an image tab. Each distinct image gets its own tab (re-clicking focuses the existing one), the tab shows a hover-revealed download button like workspace image artifacts, and the composer remove button is now a small round icon that appears on hover instead of an always-visible heavy cross.
|
✅ Qwen Triage finished — CI landed green on ✅ Qwen Triage 已完成 —— |
|
Thanks for the PR! Template looks good ✓ Problem: a real, observable UX gap rather than a theoretical concern — uploaded/pasted images in the web shell render only as small thumbnails, with no way to view them full size or download them from the transcript. The described before/after matches what the diff actually does. Direction: aligned. The artifact panel already previews workspace image artifacts (the layout, CSS, and download button exist today), so this wires user-uploaded images into an existing, maintained surface instead of adding a parallel viewer. A small, self-contained UX improvement. Size: N/A for the core-module gate — all 14 files live under Approach: the scope feels right. Reusing the existing image-artifact layout (same CSS classes) rather than building a new viewer is the correct call; a content-hash tab id for one-tab-per-image is simple, and its collision semantics are disclosed in the description. The composer remove-button restyle is technically a second concern, but it's the same composer image UX and small enough to keep together. Risk: no high-risk path signals; no elevated risk signals. Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题:这是一个真实可见的 UX 缺口,而非理论性问题——web shell 中上传/粘贴的图片只显示为小缩略图,无法查看全尺寸,也无法从 transcript 下载。描述中的 before/after 与 diff 实际改动一致。 方向:对齐。artifact 面板本来就能预览工作区图片产物(布局、CSS、下载按钮都已存在),本 PR 只是把用户上传的图片接入这个已有的、持续维护的界面,而不是新造一个预览器。是一个小而独立的 UX 改进。 规模:核心模块门槛不适用——14 个文件全部位于 方案:范围合理。复用现有图片产物布局(相同的 CSS 类)而不是新建预览器是正确选择;用内容哈希作为 tab id 实现"每张图一个 tab"很简单,碰撞语义也在描述中说明了。输入框移除按钮的重新样式严格来说是第二件事,但属于同一个输入框图片 UX,体量很小,放在一起没问题。 风险:未命中高风险路径;无升级风险信号。 进入代码审查 🔍 — Qwen Code · qwen3.8-max Reviewed at |
Code reviewBefore reading the diff, my independent proposal was: extend the artifact panel with an image tab kind, dedupe tabs with a content-derived id, pipe a click callback up from UserMessage/ChatEditor through MessageList/ChatPane into App, reuse the existing workspace image layout, and add the i18n string plus tests. The PR matches that plan closely — I didn't find a simpler path it missed. What I verified against the base tree:
Non-blocking notes:
No critical blockers and no convention violations found. Files changed (14)
TestingUnattended CI run — I don't build or run PR code myself. The evidence below is the PR's own CI on the reviewed commit, fetched through the API. The added unit tests pin the change (they would fail without the diff): click → preview callback in UserMessage and ChatEditor, tab rendering plus download href/name in ArtifactPanel. The visual layer (hover fade-in, icon, layout) is CSS-only and is captured by the Web-shell Visuals job, which was still running at review time — that layer was not independently exercised by this review. Final CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 The unit suite and the visuals capture were still running at review time; the table above is updated in place once CI settles. 中文说明代码审查在读 diff 之前,我的独立方案是:给 artifact 面板扩展一个 image tab 类型、用内容派生的 id 去重、把点击回调从 UserMessage/ChatEditor 经 MessageList/ChatPane 传到 App、复用现有的工作区图片布局,并补 i18n 文案和测试。PR 与该方案高度一致——我没有找到它遗漏的更简路径。 对照基线代码树核实的内容:
非阻塞意见:
未发现严重阻塞问题,也未发现违反项目约定的地方。 测试无人值守 CI 运行——审查本身不构建、不运行 PR 代码。下面的证据来自 PR 自身在被审 commit 上的 CI(通过 API 获取)。新增单测钉住了改动本身(没有 diff 这些测试会失败):UserMessage 和 ChatEditor 中的点击 → 预览回调,ArtifactPanel 中的 tab 渲染和下载 href/文件名。视觉层(悬停淡入、图标、布局)纯 CSS,由 Web-shell Visuals 任务截图验证,审查时该任务仍在运行——本审查未独立验证该层。 被审 commit 上:ubuntu 单测与 visuals 截图仍在进行;Desktop Shell 两个平台构建通过;macOS/Windows 单测、CLI 集成测试、tmux 测试按 CI 配置跳过。CI 结束后上方表格会被自动更新。 — Qwen Code · qwen3.8-max Reviewed at |
|
Confidence: 4/5 — a focused feature that reuses existing machinery, follows the package's conventions, and pins its behavior with tests; only nits and outstanding CI. Stepping back: the approach I would have proposed independently is essentially what this PR does — a new image tab kind in the artifact panel, content-hashed for one-tab-per-image, the existing image layout and CSS reused, callbacks threaded through both single-session and split views. Nothing in the diff tries too hard, and every change serves the stated goal; the remove-button restyle is the only adjacent edit, and it's the same composer image UX, disclosed upfront. The limitations are stated honestly — mouse-only thumbnails are a real gap, but they're called out in Risk & Scope rather than smuggled in. If I had to maintain this in six months, it reads cleanly. Two mild reservations, neither blocking: the App-level dedupe/focus logic has no unit test of its own, and thumbnail keyboard accessibility stays open (both named in the review above, both fine as follow-ups). Verdict: approve — but the unit suite and the web-shell visuals capture were still in progress on the reviewed commit at review time, so approval is deferred until CI lands green on 中文说明置信度:4/5 —— 聚焦的功能,复用了现有机制,遵循该包的约定,并用测试钉住了行为;只剩小问题和未完成的 CI。 退一步看:我独立想到的方案基本就是这个 PR 的做法——在 artifact 面板新增 image tab 类型、用内容哈希实现"每张图一个 tab"、复用现有图片布局和 CSS、在单会话与分屏两种视图下都把回调接好。diff 里没有过度设计,每处改动都服务于既定目标;移除按钮的重新样式是唯一的相邻改动,属于同一个输入框图片 UX,且事先说明。局限性也说得很坦诚——缩略图仅支持鼠标是真实缺口,但在 Risk & Scope 中明确指出,而不是偷偷带过。六个月后维护这段代码,读起来是清晰的。 两点轻微保留,均不阻塞:App 层去重/聚焦逻辑没有专属单测;缩略图的键盘可访问性暂未解决(两点都已在上面的审查中点名,都可以作为后续跟进)。 结论:通过——但审查时单测和 web-shell visuals 截图任务仍在运行,因此等 CI 在该 commit 上全绿后再批准。 — Qwen Code · qwen3.8-max Reviewed at |
🖼️ web-shell visual previewRendered against a mock daemon (no real backend): the PR base vs this PR head Screenshots · before / afterℹ️ No screenshot changed against the PR base — but this PR edits 11 render-shaping files:
Either the change has no visual effect (logic, plumbing, a state the scenarios never reach), or no scenario renders this UI — in which case the preview cannot see it, and an empty result is a coverage gap rather than a clean bill of health. To make it visible, add a scenario to Full-resolution recordings (.webm) are attached to the workflow run. — Qwen Code · web-shell visuals |
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship — CI landed green after the review. ✅
yiliang114
left a comment
There was a problem hiding this comment.
LGTM. Presentation-only and injection-safe: image srcs only ever land in / attributes (React-escaped; img cannot execute javascript: URLs), composer srcs are client-built data: URLs, and the download name is constrained to image. with the ext drawn from a sanitized MIME charset (svg+xml -> svg, non-data srcs fall back to image.png). Tab dedup by content hash focuses instead of duplicating; hash collision sharing a tab is negligible for a UI dedup. The restyled remove button keeps keyboard access via :focus-visible and gains an aria-label; disabled state hides it consistently. CI green on head. Two P3 nits, not blocking: the remove button's aria-label is hardcoded English while siblings use t(), and message-image srcs from transcripts render remote URLs as-is (tracking-pixel class, inherent to showing user content). Ship it.
|
Released in v0.21.10. |
What this PR does
Adds image preview to the Web Shell. Clicking an uploaded image in a user message, or a pasted image in the composer, opens it in the right-hand artifact panel as a dedicated image tab. Each distinct image opens its own tab (re-clicking the same image focuses the existing tab instead of duplicating it). The preview reuses the workspace image artifact layout, so hovering the preview reveals a download button in the top-right, and the downloaded file name is derived from the image MIME type. The composer's image remove button is restyled from an always-visible heavy red cross to a small round icon that fades in on hover.
Why it's needed
Uploaded and pasted images could only be seen as small thumbnails; there was no way to view them full size or download them from the transcript. This makes image attachments inspectable and retrievable, and softens the composer's remove affordance.
Reviewer Test Plan
How to verify
image.png).cd packages/web-shell && npx vitest run client/App.test.tsx client/components/ChatEditor.test.tsx client/components/messages/UserMessage.test.tsx client/components/artifacts/ArtifactPanel.test.tsx.Evidence (Before & After)
Before: images appeared only as small thumbnails with no preview, no download, and a heavy always-visible remove cross.
After: clicking any image opens a full preview tab in the right panel with a hover download button; the remove button is a subtle hover-revealed round icon.
Tested on
Environment (optional)
Local macOS workspace; unit tests only (App 356, ChatEditor 42, UserMessage, ArtifactPanel 44 — all pass; ESLint clean on changed files).
Risk & Scope
Linked Issues
N/A
中文说明
本 PR 的改动
为 Web Shell 增加图片预览。点击用户消息中的上传图片,或输入框中粘贴的图片,会在右侧 artifact 面板以独立的 image tab 打开。每张不同的图片打开各自的 tab(重复点击同一张图片会聚焦已有 tab 而非重复打开)。预览复用工作区图片 artifact 的布局,因此鼠标悬停预览区会在右上角显示下载按钮,下载文件名按图片 MIME 类型生成。输入框的图片移除按钮从常驻的粗重红色叉号,改为悬停时淡入的小圆形图标。
为什么需要
上传和粘贴的图片此前只能以小缩略图查看,无法看全尺寸,也无法从 transcript 下载。本 PR 让图片附件可以查看和下载,同时弱化了输入框的移除按钮。
Reviewer 测试计划
验证方式
image.png)。cd packages/web-shell && npx vitest run client/App.test.tsx client/components/ChatEditor.test.tsx client/components/messages/UserMessage.test.tsx client/components/artifacts/ArtifactPanel.test.tsx。前后对比证据
改动前:图片仅以小缩略图显示,无预览、无下载,移除按钮是常驻的粗重红叉。
改动后:点击任意图片在右侧面板打开全尺寸预览 tab,带悬停下载按钮;移除按钮是悬停淡入的小圆形图标。
测试平台
环境(可选)
本地 macOS 仓库;仅单元测试(App 356、ChatEditor 42、UserMessage、ArtifactPanel 44 —— 全部通过;改动文件 ESLint 通过)。
风险与范围
关联 Issue
N/A