From 891ea9bd3306ba9f8cc05b762c198d44c0f01bdc Mon Sep 17 00:00:00 2001 From: Yichen Jiang Date: Tue, 20 Oct 2026 14:30:46 +0800 Subject: [PATCH] feat(forge): show a collapsed large file as the strip of unchanged lines A large file in the changes view started behind a notice and an outlined button. It now starts as one strip drawn and opened like the collapsed unchanged lines, which names its changed line count. Binary files and files too large to show use the same strip without an action. --- .../src/client/ChangesTab.module.css | 20 +++++++++---------- .../client-ui-forge/src/client/DiffFile.tsx | 15 +++++++------- .../client-ui-forge/src/client/locales.ts | 6 ++---- .../tests/changes-tab.client.spec.tsx | 5 ++--- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/packages/experimental/client-ui-forge/src/client/ChangesTab.module.css b/packages/experimental/client-ui-forge/src/client/ChangesTab.module.css index 3273865b49..b11b200a18 100644 --- a/packages/experimental/client-ui-forge/src/client/ChangesTab.module.css +++ b/packages/experimental/client-ui-forge/src/client/ChangesTab.module.css @@ -318,15 +318,6 @@ white-space: nowrap; } -.fileMessage { - display: flex; - align-items: center; - gap: 10px; - margin: 0; - padding: 12px 16px; - color: var(--dsw-alias-label-secondary); -} - /* Lines of one file: one column of grid rows, or two cells per row side by side. */ .code { overflow-x: auto; @@ -433,24 +424,31 @@ } /* Collapsed unchanged lines; the row expands them. */ -.gap { +/* Collapsed unchanged lines, a collapsed large file, and a file whose lines cannot be drawn share one strip; + only the first two open on a click. */ +.gap, +.fileNote { display: flex; align-items: center; gap: 6px; box-sizing: border-box; width: 100%; min-height: 26px; + margin: 0; padding: 0 12px; border: 0; background: var(--forge-fill); color: var(--dsw-alias-label-tertiary); - cursor: pointer; font-family: var(--dsw-font-family); font-size: 12px; line-height: 18px; text-align: left; } +.gap { + cursor: pointer; +} + .gap:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-primary); diff --git a/packages/experimental/client-ui-forge/src/client/DiffFile.tsx b/packages/experimental/client-ui-forge/src/client/DiffFile.tsx index cd8c91f6d1..da97729464 100644 --- a/packages/experimental/client-ui-forge/src/client/DiffFile.tsx +++ b/packages/experimental/client-ui-forge/src/client/DiffFile.tsx @@ -7,7 +7,7 @@ import { useMemo, useState, type ReactNode } from 'react' import clsx from 'clsx' import { - Button, FileTypeIcon, IconChevronDownOutlineRegular, IconChevronsUpDownOutlineRegular, IconEllipsisOutlineRegular, + FileTypeIcon, IconChevronDownOutlineRegular, IconChevronsUpDownOutlineRegular, IconEllipsisOutlineRegular, languageForPath, Menu, MenuItemButton, PathLabel, useCodeHighlighter, type CodeHighlighter, type HighlightSpan, } from '@deepseek-ai/dsh-client-ui-primitives' import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots' @@ -177,15 +177,16 @@ function Lines({ file, text, open, onExpand, split, wrap, t }: Pick{t('diff.binary')}

- if (file.oversized) return

{t('diff.fileTooLarge')}

+ if (file.binary) return

{t('diff.binary')}

+ if (file.oversized) return

{t('diff.fileTooLarge')}

if (file.hunks.length === 0) return null if (large && !revealed) { + // A large file starts as one collapsed strip, drawn and opened like the collapsed unchanged lines. return ( -
- {t('diff.oversized')} - -
+ ) } return diff --git a/packages/experimental/client-ui-forge/src/client/locales.ts b/packages/experimental/client-ui-forge/src/client/locales.ts index cb923b5c67..6da70da036 100644 --- a/packages/experimental/client-ui-forge/src/client/locales.ts +++ b/packages/experimental/client-ui-forge/src/client/locales.ts @@ -117,8 +117,7 @@ export const zh = { 'diff.badgeUncommitted': '未提交', 'diff.binary': '二进制文件,无法显示变更', 'diff.binaryLabel': '二进制', - 'diff.oversized': '文件较大,默认收起', - 'diff.showAnyway': '仍然显示', + 'diff.largeCollapsed': '文件较大,{count} 行变更已收起', 'diff.fileTooLarge': '文件太大,无法显示变更', 'diff.error': '无法读取变更', 'diff.tooLarge': '变更太大,无法在这里显示', @@ -313,8 +312,7 @@ export const en: Record = { 'diff.badgeUncommitted': 'Uncommitted', 'diff.binary': 'Binary file; its changes cannot be shown', 'diff.binaryLabel': 'Binary', - 'diff.oversized': 'Large file, collapsed by default', - 'diff.showAnyway': 'Show anyway', + 'diff.largeCollapsed': 'Large file: {count} changed lines collapsed', 'diff.fileTooLarge': 'This file is too large to show', 'diff.error': 'The changes could not be read', 'diff.tooLarge': 'These changes are too large to show here', diff --git a/packages/experimental/client-ui-forge/tests/changes-tab.client.spec.tsx b/packages/experimental/client-ui-forge/tests/changes-tab.client.spec.tsx index 9db4235c6f..4e5b8036f2 100644 --- a/packages/experimental/client-ui-forge/tests/changes-tab.client.spec.tsx +++ b/packages/experimental/client-ui-forge/tests/changes-tab.client.spec.tsx @@ -437,13 +437,12 @@ describe('ChangesTab layout', () => { expect(m.section('src/app.ts').querySelector(`.${css.code}`)).not.toBeNull() const first = m.section('data/huge-1.txt') - expect(within(first).getByText(en['diff.oversized'])).toBeTruthy() - fireEvent.click(within(first).getByRole('button', { name: en['diff.showAnyway'] })) + fireEvent.click(within(first).getByRole('button', { name: 'Large file: 1,001 changed lines collapsed' })) // A file with additions only keeps one column in the side-by-side layout. expect(first.querySelectorAll('[data-diff-line="add"]')).toHaveLength(1001) expect(first.querySelector('[data-diff-pair]')).toBeNull() fireEvent.click(within(m.section('data/huge-6.txt')).getByRole('button', { name: 'Expand huge-6.txt' })) - expect(within(m.section('data/huge-6.txt')).getByText(en['diff.oversized'])).toBeTruthy() + expect(within(m.section('data/huge-6.txt')).getByRole('button', { name: 'Large file: 1,001 changed lines collapsed' })).toBeTruthy() }) it('collapses every file from the toolbar while any is expanded, and expands every file once all are collapsed', async () => {