Parcourir la source

fix(web): preserve office file icons and lazy sidebar replay

creatixchu il y a 1 mois
Parent
commit
9961eedec8

+ 2 - 2
.agents/notes/implemented/feature/2026-09-08-shared-file-type-icons.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-09-08-shared-file-type-icons.md
-2026-09-08-shared-file-type-icons.md: 0844cb8828edafe135d4f35b6b942691998b8b97
-2026-09-08-shared-file-type-icons.zh.md: 6d10a5669a3c68cfa327997f6822547689e3df1a
+2026-09-08-shared-file-type-icons.md: 95380fd642e574389cbdc0d10038e2a0a8d85283
+2026-09-08-shared-file-type-icons.zh.md: 7ba0254206dc026a8967f86036e1bf329ac9ff21

+ 2 - 2
.agents/notes/implemented/feature/2026-09-08-shared-file-type-icons.md

@@ -10,9 +10,9 @@ Client feature plugins can share React components only through `@deepseek-ai/dsh
 
 ## Decision
 
-`ui-primitives` owns one Cordis-free file classification and rendering API. `fileExtension(path)` applies the shared basename and final-dot semantics to either path separator. `classifyFileType(path)` matches without case sensitivity and returns the closed `FileType` union: the traditional `code`, `excel`, `folder`, `html`, `image`, `markdown`, `other`, `pdf`, `ppt`, `video`, and `word` categories plus the detailed `CodeFileType` set imported from the supplied `square-code-icons` map. Exact filenames, filename prefixes, filename suffixes, optional project context, and extensions run in that order. The path classifier returns every member except `folder`; callers use the explicit `FileTypeIcon` `type` override when they know an entry is a directory. Unknown extensions, missing extensions, and trailing dots resolve to `other`, except the shared table recognizes named files such as `Dockerfile`, `Makefile`, `package.json`, `.gitignore`, `README`, and `CHANGELOG`.
+`ui-primitives` owns one Cordis-free file classification and rendering API. `fileExtension(path)` applies the shared basename and final-dot semantics to either path separator. `classifyFileType(path)` matches without case sensitivity and returns the closed `FileType` union: the traditional `code`, `excel`, `folder`, `html`, `image`, `markdown`, `other`, `pdf`, `ppt`, `video`, and `word` categories plus the detailed `CodeFileType` categories rendered by `CodeFileIcon`. Exact filenames, filename prefixes, filename suffixes, optional project context, and extensions run in that order. The path classifier returns every member except `folder`; callers use the explicit `FileTypeIcon` `kind` override when they know an entry is a directory. Unknown extensions, missing extensions, and trailing dots resolve to `other`, except the shared table recognizes named files such as `Dockerfile`, `Makefile`, `package.json`, `.gitignore`, `README`, and `CHANGELOG`.
 
-`FileTypeIcon` accepts a path, shared `IconProps`, the optional explicit type, and an optional project-file snapshot. Traditional file types render the supplied 28px document and folder contours as inline SVG. Excel, Markdown, PDF, PPT, and Word foreground marks scale to 122% around their visual center; the remaining marked traditional glyphs use 112%, while the file body and folded corner retain their source geometry and the generic file has no invented center mark. The sheet is a solid category color, the foreground mark and ordinary folded corner are white, and the generic file has a darker grey corner. CSS assigns the supplied category palette through static design tokens: DeepSeek blue for code/HTML/Markdown, the lighter DeepSeek blue for Word, green for Excel, two amber steps for folder/PPT, red for PDF, and neutral grey for unknown files. Image and video share the supplied violet through a component-local variable because the design platform has no matching violet token. A caller may override a traditional sheet through `--dsh-file-type-icon-color`.
+`FileTypeIcon` accepts a path, shared `IconProps`, the explicit `kind`, and an optional project-file snapshot. Traditional file types render the supplied 28px document and folder contours as inline SVG. Excel, Markdown, PDF, PPT, and Word foreground marks scale to 122% around their visual center; the remaining marked traditional glyphs use 112%, while the file body and folded corner retain their source geometry and the generic file has no invented center mark. The sheet is a solid category color, the foreground mark and ordinary folded corner are white, and the generic file has a darker grey corner. CSS assigns the supplied category palette through static design tokens: DeepSeek blue for code/HTML/Markdown, the lighter DeepSeek blue for Word, green for Excel, two amber steps for folder/PPT, red for PDF, and neutral grey for unknown files. Image and video share the supplied violet through a component-local variable because the design platform has no matching violet token. A caller may override a traditional sheet through `--dsh-file-type-icon-color`.
 
 Recognized code and configuration files render the corresponding 20px square artwork scaled to the requested icon size. These technology marks retain their embedded multicolor fills and are the explicit exception to the ordinary current-color icon rule. The map selects React before TypeScript/JavaScript, Angular filename suffixes before their base extension, Docker/Node/Git/Make/CMake by filename rules, and Flutter only when the optional project snapshot contains a `pubspec.yaml` whose text includes `flutter:`. Markdown and SVG remain owned by the traditional Markdown and image categories. Every traditional and technology SVG is `aria-hidden`, and the card, row, or button that owns the file identity supplies the accessible name.
 

+ 1 - 1
.agents/notes/implemented/feature/2026-09-08-shared-file-type-icons.zh.md

@@ -10,7 +10,7 @@ Status: implemented
 
 ## 决策
 
-`ui-primitives` 统一拥有一套 Cordis-free 的文件分类与渲染 API。`fileExtension(path)` 对两种路径分隔符采用共享的 basename 与最终点号语义。`classifyFileType(path)` 不区分大小写,并返回闭合的 `FileType` 联合:传统的 `code`、`excel`、`folder`、`html`、`image`、`markdown`、`other`、`pdf`、`ppt`、`video`、`word` 类别,以及从所提供 `square-code-icons` 映射接入的细分 `CodeFileType` 集合。解析按完整文件名、文件名前缀、文件名后缀、可选项目上下文、扩展名的顺序执行。路径分类器返回 `folder` 之外的全部成员;调用方确认条目是目录时,通过 `FileTypeIcon` 的显式 `type` 覆盖指定目录。未知扩展名、无扩展名和末尾点号回退到 `other`,但共享表识别 `Dockerfile`、`Makefile`、`package.json`、`.gitignore`、`README`、`CHANGELOG` 等具名文件。
+`ui-primitives` 统一拥有一套 Cordis-free 的文件分类与渲染 API。`fileExtension(path)` 对两种路径分隔符采用共享的 basename 与最终点号语义。`classifyFileType(path)` 不区分大小写,并返回闭合的 `FileType` 联合:传统的 `code`、`excel`、`folder`、`html`、`image`、`markdown`、`other`、`pdf`、`ppt`、`video`、`word` 类别,以及由 `CodeFileIcon` 渲染的细分 `CodeFileType` 集合。解析按完整文件名、文件名前缀、文件名后缀、可选项目上下文、扩展名的顺序执行。路径分类器返回 `folder` 之外的全部成员;调用方确认条目是目录时,通过 `FileTypeIcon` 的显式 `kind` 覆盖指定目录。未知扩展名、无扩展名和末尾点号回退到 `other`,但共享表识别 `Dockerfile`、`Makefile`、`package.json`、`.gitignore`、`README`、`CHANGELOG` 等具名文件。
 
 `FileTypeIcon` 接受路径、共享 `IconProps`、可选的显式类型和可选的项目文件快照。传统文件类型把所提供的 28px 文档与文件夹轮廓渲染为 inline SVG。Excel、Markdown、PDF、PPT、Word 的前景标记围绕自身视觉中心缩放至 122%,其余带标记的传统图形使用 112%;文件底板与折角保持源图几何,通用文件不凭空增加中心标记。底板使用实色分类颜色,前景标记与普通折角使用白色,通用文件使用较深的灰色折角。CSS 通过静态设计 token 分配所提供的分类调色板:code/HTML/Markdown 使用 DeepSeek 蓝,Word 使用较浅的 DeepSeek 蓝,Excel 使用绿色,folder/PPT 使用两档琥珀色,PDF 使用红色,未知文件使用中性灰。image 与 video 通过组件本地变量共用所提供的紫色,因为设计平台没有匹配的紫色 token。调用方可通过 `--dsh-file-type-icon-color` 覆盖传统底板颜色。
 

+ 1 - 1
apps/web/tests/seeded-history.e2e.ts

@@ -420,7 +420,7 @@ describe('web e2e: seeded history renders through cold resume', () => {
     await fileLink.click()
     await expect.poll(() => frame.getAttribute('data-rightbar-collapsed'), { timeout: 5_000 }).toBe(null)
     const column = page.locator('[data-rightbar-col]')
-    await expect.poll(() => column.locator('[data-dockkit-tab-title]').count(), { timeout: 5_000 }).toBe(2)
+    await expect.poll(() => column.locator('[data-dockkit-tab-title]').allTextContents(), { timeout: 5_000 }).toEqual(['a.txt'])
     // Path label survives from the recorded args (a.txt).
     await expect.poll(() => page.getByText('a.txt', { exact: false }).count(), { timeout: 5_000 }).toBeGreaterThan(0)
     const path = column.locator('[data-textpreview-path]')

+ 2 - 2
packages/client/ui-primitives/README.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write packages/client/ui-primitives/README.md
-README.md: d6e6a101c9c4397532ac84bc27c519f9d02dcdaf
-README.zh.md: 1c41e5185d8f0701bf4d5bd377f1a77b83401bfa
+README.md: c511f1de3bd1b16f52ec73297122cd3b575f7c56
+README.zh.md: e8c92fdd6bf91e349fe5ec16271588bf4a9eed02

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
packages/client/ui-primitives/README.md


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
packages/client/ui-primitives/README.zh.md


+ 6 - 0
packages/client/ui-primitives/src/FileTypeIcon.tsx

@@ -77,6 +77,7 @@ const EXTENSION_TYPES: Readonly<Record<string, ClassifiedFileType>> = {
   pdf: 'pdf',
   ppt: 'ppt',
   pptx: 'ppt',
+  key: 'ppt',
   mp4: 'video',
   mov: 'video',
   m4v: 'video',
@@ -87,8 +88,13 @@ const EXTENSION_TYPES: Readonly<Record<string, ClassifiedFileType>> = {
   mpeg: 'video',
   doc: 'word',
   docx: 'word',
+  rtf: 'word',
+  odt: 'word',
+  pages: 'word',
   xls: 'excel',
   xlsx: 'excel',
+  xlsm: 'excel',
+  numbers: 'excel',
 }
 
 const NAME_TYPES: Readonly<Record<string, ClassifiedFileType>> = {

+ 1 - 1
packages/client/ui-primitives/src/code-file-types.ts

@@ -1,4 +1,4 @@
-/** Full-color code and configuration glyphs supplied by square-code-icons v1. */
+/** Code and configuration categories with embedded full-color glyphs. */
 export const CODE_FILE_TYPES = [
   'angular',
   'c',

+ 6 - 0
packages/client/ui-primitives/tests/file-type-icon.client.spec.tsx

@@ -28,6 +28,12 @@ describe('classifyFileType', () => {
     ['data/export.CSV', 'code'],
     ['shots/hero.png', 'image'],
     ['notes/README.MDX', 'markdown'],
+    ['report.xlsm', 'excel'],
+    ['budget.numbers', 'excel'],
+    ['deck.key', 'ppt'],
+    ['letter.rtf', 'word'],
+    ['letter.odt', 'word'],
+    ['letter.pages', 'word'],
     ['report.pdf', 'pdf'],
     ['deck.pptx', 'ppt'],
     ['clip.webm', 'video'],

+ 6 - 0
packages/client/ui-primitives/tests/link-icon.client.spec.tsx

@@ -11,6 +11,12 @@ describe('classifyLinkPath', () => {
     ['site/index.html', 'code'],
     ['data/export.CSV', 'code'],
     ['shots/hero.png', 'image'],
+    ['report.xlsm', 'document'],
+    ['budget.numbers', 'document'],
+    ['deck.key', 'document'],
+    ['letter.rtf', 'document'],
+    ['letter.odt', 'document'],
+    ['letter.pages', 'document'],
     ['report.pdf', 'document'],
     ['budget.xlsx', 'document'],
     ['deck.pptx', 'document'],

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff