From fa128afdb50428270030d904faeec351210852f3 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Sun, 14 Jun 2026 00:51:12 +0300 Subject: [PATCH] Refine changes panel controls --- .../ui/src/components/layout/ContextPanel.tsx | 16 +- packages/ui/src/components/layout/Header.tsx | 47 ++++++ packages/ui/src/components/views/DiffView.tsx | 147 +++++++++++++++--- packages/ui/src/index.css | 35 +++++ packages/ui/src/lib/i18n/messages/en.ts | 7 +- packages/ui/src/lib/i18n/messages/es.ts | 7 +- packages/ui/src/lib/i18n/messages/fr.ts | 7 +- packages/ui/src/lib/i18n/messages/ko.ts | 7 +- packages/ui/src/lib/i18n/messages/pl.ts | 7 +- packages/ui/src/lib/i18n/messages/pt-BR.ts | 7 +- packages/ui/src/lib/i18n/messages/uk.ts | 7 +- packages/ui/src/lib/i18n/messages/zh-CN.ts | 7 +- packages/ui/src/lib/i18n/messages/zh-TW.ts | 7 +- packages/ui/src/stores/useUIStore.ts | 5 +- 14 files changed, 277 insertions(+), 36 deletions(-) diff --git a/packages/ui/src/components/layout/ContextPanel.tsx b/packages/ui/src/components/layout/ContextPanel.tsx index 7ab0b581..c1886424 100644 --- a/packages/ui/src/components/layout/ContextPanel.tsx +++ b/packages/ui/src/components/layout/ContextPanel.tsx @@ -199,7 +199,7 @@ const getTabLabel = ( } if (tab.mode === 'diff') { - return tab.stagedDiff ? t('contextPanel.mode.stagedDiff') : t('contextPanel.mode.workingDiff'); + return t('contextPanel.mode.diff'); } return getModeLabel(tab.mode, t); @@ -1997,6 +1997,7 @@ export const ContextPanel: React.FC = () => { const panelState = useUIStore((state) => (directoryKey ? state.contextPanelByDirectory[directoryKey] : undefined)); const closeContextPanel = useUIStore((state) => state.closeContextPanel); const closeContextPanelTab = useUIStore((state) => state.closeContextPanelTab); + const openContextPanelTab = useUIStore((state) => state.openContextPanelTab); const toggleContextPanelExpanded = useUIStore((state) => state.toggleContextPanelExpanded); const setContextPanelWidth = useUIStore((state) => state.setContextPanelWidth); const setActiveContextPanelTab = useUIStore((state) => state.setActiveContextPanelTab); @@ -2178,6 +2179,18 @@ export const ContextPanel: React.FC = () => { const activeChatTabID = activeTab?.mode === 'chat' ? activeTab.id : null; + const handleDiffScopeChange = React.useCallback((nextScope: 'working' | 'staged') => { + if (!directoryKey || activeTab?.mode !== 'diff') { + return; + } + + openContextPanelTab(directoryKey, { + mode: 'diff', + targetPath: activeTab.targetPath, + stagedDiff: nextScope === 'staged', + }); + }, [activeTab, directoryKey, openContextPanelTab]); + const postThemeSyncToEmbeddedChat = React.useCallback(() => { if (typeof window === 'undefined') { return; @@ -2286,6 +2299,7 @@ export const ContextPanel: React.FC = () => { pinSelectedFileHeaderToTopOnNavigate showOpenInEditorAction diffScope={activeTab.stagedDiff ? 'staged' : 'working'} + onDiffScopeChange={handleDiffScopeChange} targetFilePath={activeTab.targetPath} flushContent /> diff --git a/packages/ui/src/components/layout/Header.tsx b/packages/ui/src/components/layout/Header.tsx index 5168a1be..58a7d3ab 100644 --- a/packages/ui/src/components/layout/Header.tsx +++ b/packages/ui/src/components/layout/Header.tsx @@ -717,6 +717,7 @@ export const Header: React.FC = ({ const openContextOverview = useUIStore((state) => state.openContextOverview); const openContextPlan = useUIStore((state) => state.openContextPlan); const openContextBrowser = useUIStore((state) => state.openContextBrowser); + const openContextPanelTab = useUIStore((state) => state.openContextPanelTab); const closeContextPanel = useUIStore((state) => state.closeContextPanel); const contextPanelByDirectory = useUIStore((state) => state.contextPanelByDirectory); const activeMainTab = useUIStore((state) => state.activeMainTab); @@ -1495,6 +1496,21 @@ export const Header: React.FC = ({ openContextPlan(directory); }, [closeContextPanel, contextPanelByDirectory, openContextPlan, openDirectory]); + const handleOpenContextChanges = React.useCallback(() => { + const directory = normalize(openDirectory || ''); + if (!directory) { + return; + } + + const panelState = contextPanelByDirectory[directory]; + if (getActiveContextMode(panelState) === 'diff') { + closeContextPanel(directory); + return; + } + + openContextPanelTab(directory, { mode: 'diff', stagedDiff: false }); + }, [closeContextPanel, contextPanelByDirectory, openContextPanelTab, openDirectory]); + const handleOpenContextBrowser = React.useCallback(() => { const directory = normalize(openDirectory || ''); if (!directory) { @@ -1519,6 +1535,15 @@ export const Header: React.FC = ({ return getActiveContextMode(panelState) === 'plan'; }, [contextPanelByDirectory, openDirectory]); + const isContextChangesActive = React.useMemo(() => { + const directory = normalize(openDirectory || ''); + if (!directory) { + return false; + } + const panelState = contextPanelByDirectory[directory]; + return getActiveContextMode(panelState) === 'diff'; + }, [contextPanelByDirectory, openDirectory]); + const isContextBrowserActive = React.useMemo(() => { const directory = normalize(openDirectory || ''); if (!directory) { @@ -1992,6 +2017,28 @@ export const Header: React.FC = ({ const desktopSidebarActions = ( <> + {!isVSCode ? ( + + + + + +

{t('header.actions.toggleChangesPanel')}

+
+
+ ) : null} {showPlanTab && ( diff --git a/packages/ui/src/components/views/DiffView.tsx b/packages/ui/src/components/views/DiffView.tsx index c1887fa7..c27f5237 100644 --- a/packages/ui/src/components/views/DiffView.tsx +++ b/packages/ui/src/components/views/DiffView.tsx @@ -176,12 +176,22 @@ const createTextDiffDataFromPatch = (filePath: string, patch: string): DiffData }; }; -const formatDiffTotals = (insertions?: number, deletions?: number) => { +const formatDiffTotals = ( + insertions?: number, + deletions?: number, + options?: { shrink?: boolean; className?: string }, +) => { const added = insertions ?? 0; const removed = deletions ?? 0; if (!added && !removed) return null; return ( - + {added ? +{added} : null} {removed ? -{removed} : null} @@ -232,6 +242,7 @@ interface FileSelectorProps { selectedFile: string | null; selectedFileEntry: FileEntry | null; onSelectFile: (path: string) => void; + className?: string; } const FileSelector = React.memo(({ @@ -239,6 +250,7 @@ const FileSelector = React.memo(({ selectedFile, selectedFileEntry, onSelectFile, + className, }) => { const { t } = useI18n(); @@ -247,24 +259,27 @@ const FileSelector = React.memo(({ return ( - - + {changedFiles.map((file) => ( -
+
{formatDiffTotals(file.insertions, file.deletions)} @@ -277,6 +292,64 @@ const FileSelector = React.memo(({ ); }); +interface ChangeScopeSelectorProps { + scope: Extract; + workingCount: number; + stagedCount: number; + onScopeChange?: (scope: Extract) => void; +} + +const ChangeScopeSelector = React.memo(({ + scope, + workingCount, + stagedCount, + onScopeChange, +}) => { + const { t } = useI18n(); + const currentCount = scope === 'staged' ? stagedCount : workingCount; + const currentLabel = scope === 'staged' ? t('diffView.scope.staged') : t('diffView.scope.changed'); + + return ( + + + + + + { + if (value === 'working' || value === 'staged') { + onScopeChange?.(value); + } + }} + > + + + {t('diffView.scope.changed')} + {workingCount} + + + + + {t('diffView.scope.staged')} + {stagedCount} + + + + + + ); +}); + interface FileListProps { changedFiles: FileEntry[]; selectedFile: string | null; @@ -766,6 +839,7 @@ interface DiffViewProps { pinSelectedFileHeaderToTopOnNavigate?: boolean; showOpenInEditorAction?: boolean; diffScope?: DiffScope; + onDiffScopeChange?: (scope: Extract) => void; targetFilePath?: string | null; /** Render diff content flush with the container edges (no outer padding). */ flushContent?: boolean; @@ -778,6 +852,7 @@ export const DiffView: React.FC = ({ pinSelectedFileHeaderToTopOnNavigate = false, showOpenInEditorAction = false, diffScope = 'all', + onDiffScopeChange, targetFilePath = null, flushContent = false, }) => { @@ -868,6 +943,16 @@ export const DiffView: React.FC = ({ .sort((a, b) => a.path.localeCompare(b.path)); }, [diffScope, status]); + const workingFileCount = React.useMemo(() => { + if (!status?.files) return 0; + return status.files.filter(isWorkingStatusFile).length; + }, [status]); + + const stagedFileCount = React.useMemo(() => { + if (!status?.files) return 0; + return status.files.filter(isStagedStatusFile).length; + }, [status]); + const selectedFileEntry = React.useMemo(() => { if (!selectedFile) return null; return changedFiles.find((file) => file.path === selectedFile) ?? null; @@ -1391,18 +1476,26 @@ export const DiffView: React.FC = ({ return (
-
+
{!isMobile && ( -
- - - {isLoadingStatus && !status - ? t('diffView.state.loadingChanges') - : (changedFiles.length === 1 - ? t('diffView.summary.changedFilesSingle', { count: changedFiles.length }) - : t('diffView.summary.changedFilesPlural', { count: changedFiles.length }))} - -
+ diffScope === 'working' || diffScope === 'staged' ? ( + + ) : ( +
+ + {isLoadingStatus && !status + ? t('diffView.state.loadingChanges') + : (changedFiles.length === 1 + ? t('diffView.summary.changedFilesSingle', { count: changedFiles.length }) + : t('diffView.summary.changedFilesPlural', { count: changedFiles.length }))} + +
+ ) )} {showFileSelector && ( = ({ selectedFile={selectedFile} selectedFileEntry={selectedFileEntry} onSelectFile={handleSelectFileAndScroll} + className="w-fit min-w-0" /> )} -
+ {!showFileSelector ?
: null} {changedFiles.length > 0 && ( diff --git a/packages/ui/src/index.css b/packages/ui/src/index.css index b0e97e46..9e41239b 100644 --- a/packages/ui/src/index.css +++ b/packages/ui/src/index.css @@ -857,6 +857,41 @@ html:not(.dark) .chat-scroll { } } +/* Diff toolbar: drop low-priority labels as the context panel narrows. */ +@container diff-toolbar (max-width: 34rem) { + .diff-toolbar__file-stats { + display: none; + } +} + +@container diff-toolbar (max-width: 40rem) { + .diff-toolbar__scope-count, + .diff-toolbar__expand-label { + display: none; + } + + .diff-toolbar__expand-button { + padding-inline: 0.5rem; + } +} + +@container diff-toolbar (max-width: 29rem) { + .diff-toolbar__file-label { + display: none; + } + + .diff-toolbar__file-trigger { + flex: 0 0 auto; + gap: 0.375rem; + padding-inline: 0.625rem; + } + + .diff-toolbar__file-trigger-content { + flex: 0 0 auto; + gap: 0; + } +} + /* Status row: collapse optional text when narrow to keep both sides in one line. */ @container status-row (max-width: 30rem) { .status-row__active-todo { diff --git a/packages/ui/src/lib/i18n/messages/en.ts b/packages/ui/src/lib/i18n/messages/en.ts index 4cf212aa..016137c4 100644 --- a/packages/ui/src/lib/i18n/messages/en.ts +++ b/packages/ui/src/lib/i18n/messages/en.ts @@ -953,7 +953,7 @@ export const dict = { 'gitView.worktree.availableInWorktreeMode': 'Available only in worktree mode', 'contextPanel.mode.chat': 'Chat', 'contextPanel.mode.files': 'Files', - 'contextPanel.mode.diff': 'Diff', + 'contextPanel.mode.diff': 'Changes', 'contextPanel.mode.stagedDiff': 'Staged Diff', 'contextPanel.mode.workingDiff': 'Working Diff', 'contextPanel.mode.plan': 'Plan', @@ -1202,6 +1202,9 @@ export const dict = { 'diffView.state.largeDiffDescription': 'Rendering may be slow. You can still view the diff by clicking below.', 'diffView.summary.changedFilesSingle': '{count} file changed', 'diffView.summary.changedFilesPlural': '{count} files changed', + 'diffView.scope.changed': 'Changed', + 'diffView.scope.staged': 'Staged', + 'diffView.scope.selectorAria': 'Select change mode', 'diffView.actions.retry': 'Retry', 'diffView.actions.renderAnyway': 'Render anyway', 'diffView.actions.expandAll': 'Expand all', @@ -1298,6 +1301,8 @@ export const dict = { 'header.services.modelFamily.other': 'Other', 'header.services.shutdownDev': 'Stop OpenChamber', 'header.actions.openPlanAria': 'Open plan', + 'header.actions.toggleChangesPanel': 'Changes panel', + 'header.actions.toggleChangesPanelAria': 'Toggle changes panel', 'header.actions.planWithShortcut': 'Plan ({shortcut})', 'header.actions.terminalPanelWithShortcut': 'Terminal panel ({shortcut})', 'header.actions.toggleTerminalPanelAria': 'Toggle terminal panel', diff --git a/packages/ui/src/lib/i18n/messages/es.ts b/packages/ui/src/lib/i18n/messages/es.ts index 29cb0759..136a78f8 100644 --- a/packages/ui/src/lib/i18n/messages/es.ts +++ b/packages/ui/src/lib/i18n/messages/es.ts @@ -954,7 +954,7 @@ export const dict: Record = { "gitView.worktree.availableInWorktreeMode": "Disponible solo en modo worktree", "contextPanel.mode.chat": "Chat", "contextPanel.mode.files": "Archivos", - "contextPanel.mode.diff": "Diff", + "contextPanel.mode.diff": "Cambios", "contextPanel.mode.stagedDiff": "Staged Diff", "contextPanel.mode.workingDiff": "Working Diff", "contextPanel.mode.plan": "Plan", @@ -1168,6 +1168,9 @@ export const dict: Record = { "diffView.state.largeDiffDescription": "El renderizado puede ser lento. Aun así puedes ver el diff con el botón de abajo.", "diffView.summary.changedFilesSingle": "{count} archivo modificado", "diffView.summary.changedFilesPlural": "{count} archivos modificados", + "diffView.scope.changed": "Cambiados", + "diffView.scope.staged": "Staged", + "diffView.scope.selectorAria": "Seleccionar modo de cambios", "diffView.actions.retry": "Volver a intentar", "diffView.actions.renderAnyway": "Renderizar de todos modos", "diffView.actions.expandAll": "Expandir todo", @@ -1264,6 +1267,8 @@ export const dict: Record = { "header.services.modelFamily.other": "Otro", "header.services.shutdownDev": "Detener OpenChamber", "header.actions.openPlanAria": "Abrir plan", + "header.actions.toggleChangesPanel": "Panel de cambios", + "header.actions.toggleChangesPanelAria": "Alternar panel de cambios", "header.actions.planWithShortcut": "Plan ({shortcut})", "header.actions.terminalPanelWithShortcut": "Panel de terminal ({shortcut})", "header.actions.toggleTerminalPanelAria": "Mostrar u ocultar panel de terminal", diff --git a/packages/ui/src/lib/i18n/messages/fr.ts b/packages/ui/src/lib/i18n/messages/fr.ts index c5bdfae3..e8ffe365 100644 --- a/packages/ui/src/lib/i18n/messages/fr.ts +++ b/packages/ui/src/lib/i18n/messages/fr.ts @@ -831,7 +831,7 @@ export const dict = { 'gitView.worktree.availableInWorktreeMode': 'Disponible uniquement en mode worktree', 'contextPanel.mode.chat': 'Chat', 'contextPanel.mode.files': 'Fichiers', - 'contextPanel.mode.diff': 'Différence', + "contextPanel.mode.diff": "Changements", 'contextPanel.mode.stagedDiff': 'Différence par étapes', 'contextPanel.mode.workingDiff': 'Différentiel de travail', 'contextPanel.mode.plan': 'Plan', @@ -1075,6 +1075,9 @@ export const dict = { 'diffView.state.largeDiffDescription': 'Le rendu peut être lent. Vous pouvez tout de même afficher le diff avec le bouton ci-dessous.', 'diffView.summary.changedFilesSingle': 'Le fichier {count} a été modifié', 'diffView.summary.changedFilesPlural': 'Fichiers {count} modifiés', + "diffView.scope.changed": "Modifiés", + "diffView.scope.staged": "Staged", + "diffView.scope.selectorAria": "Sélectionner le mode de changements", 'diffView.actions.retry': 'Réessayer', 'diffView.actions.renderAnyway': 'Afficher quand même', 'diffView.actions.expandAll': 'Tout développer', @@ -1164,6 +1167,8 @@ export const dict = { 'header.services.modelFamily.other': 'Autre', 'header.services.shutdownDev': 'Arrêter OpenChamber', 'header.actions.openPlanAria': 'Plan ouvert', + "header.actions.toggleChangesPanel": "Panneau des changements", + "header.actions.toggleChangesPanelAria": "Basculer le panneau des changements", 'header.actions.planWithShortcut': 'Forfait ({shortcut})', 'header.actions.terminalPanelWithShortcut': 'Panneau à bornes ({shortcut})', 'header.actions.toggleTerminalPanelAria': 'Basculer le panneau à bornes', diff --git a/packages/ui/src/lib/i18n/messages/ko.ts b/packages/ui/src/lib/i18n/messages/ko.ts index a5bd1d77..f9a49eb3 100644 --- a/packages/ui/src/lib/i18n/messages/ko.ts +++ b/packages/ui/src/lib/i18n/messages/ko.ts @@ -954,7 +954,7 @@ export const dict: Record = { 'gitView.worktree.availableInWorktreeMode': '워크트리 모드에서만 사용할 수 있습니다', 'contextPanel.mode.chat': '채팅', 'contextPanel.mode.files': '파일', - 'contextPanel.mode.diff': '변경사항', + "contextPanel.mode.diff": "Changes", 'contextPanel.mode.stagedDiff': 'Staged Diff', 'contextPanel.mode.workingDiff': 'Working Diff', 'contextPanel.mode.plan': '계획', @@ -1205,6 +1205,9 @@ export const dict: Record = { 'diffView.state.largeDiffDescription': '렌더링이 느릴 수 있습니다. 아래 버튼으로 diff를 계속 볼 수 있습니다.', 'diffView.summary.changedFilesSingle': '파일 {count}개 변경됨', 'diffView.summary.changedFilesPlural': '파일 {count}개 변경됨', + "diffView.scope.changed": "Changed", + "diffView.scope.staged": "Staged", + "diffView.scope.selectorAria": "변경 모드 선택", 'diffView.actions.retry': '다시 시도', 'diffView.actions.renderAnyway': '그래도 렌더링', 'diffView.actions.expandAll': '모두 펼치기', @@ -1300,6 +1303,8 @@ export const dict: Record = { 'header.services.remaining': '남은 양', 'header.services.modelFamily.other': '기타', 'header.actions.openPlanAria': '플랜 열기', + "header.actions.toggleChangesPanel": "변경 패널", + "header.actions.toggleChangesPanelAria": "변경 패널 전환", 'header.actions.planWithShortcut': '플랜 ({shortcut})', 'header.actions.terminalPanelWithShortcut': '터미널 패널 ({shortcut})', 'header.actions.toggleTerminalPanelAria': '토글 터미널 패널', diff --git a/packages/ui/src/lib/i18n/messages/pl.ts b/packages/ui/src/lib/i18n/messages/pl.ts index 7b9bf6c9..fd96371a 100644 --- a/packages/ui/src/lib/i18n/messages/pl.ts +++ b/packages/ui/src/lib/i18n/messages/pl.ts @@ -1244,7 +1244,7 @@ export const dict: Record = { 'contextPanel.iframe.sessionChatTitle': 'Czat sesji {sessionID}', 'contextPanel.mode.chat': 'Chat', 'contextPanel.mode.context': 'Context', - 'contextPanel.mode.diff': 'Różnice', + "contextPanel.mode.diff": "Zmiany", 'contextPanel.mode.stagedDiff': 'Staged Diff', 'contextPanel.mode.workingDiff': 'Working Diff', 'contextPanel.mode.files': 'Pliki', @@ -1440,6 +1440,9 @@ export const dict: Record = { 'diffView.state.notGitRepository': 'To nie jest repozytorium Git. Użyj karty Git, aby zainicjować lub zmienić katalog.', 'diffView.state.selectSessionDirectory': 'Wybierz katalog sesji, aby zobaczyć diffy', 'diffView.summary.changedFilesPlural': 'Zmieniono {count} plików', + "diffView.scope.changed": "Zmienione", + "diffView.scope.staged": "Staged", + "diffView.scope.selectorAria": "Wybierz tryb zmian", 'diffView.summary.changedFilesSingle': 'Zmieniono {count} plik', 'directoryExplorerDialog.actions.addProject': 'Dodaj projekt', 'directoryExplorerDialog.actions.addLocalProject': 'Dodaj projekt lokalny', @@ -1950,6 +1953,8 @@ export const dict: Record = { 'header.actions.newSessionAria': 'Nowa sesja', 'header.actions.newSessionWithShortcut': 'Nowa sesja ({shortcut})', 'header.actions.openPlanAria': 'Otwórz plan', + "header.actions.toggleChangesPanel": "Panel zmian", + "header.actions.toggleChangesPanelAria": "Przełącz panel zmian", 'header.actions.openSessionsAria': 'Otwórz sesje', 'header.actions.openAppMenu': 'Menu OpenChamber', 'header.actions.openAppMenuAria': 'Otwórz menu OpenChamber', diff --git a/packages/ui/src/lib/i18n/messages/pt-BR.ts b/packages/ui/src/lib/i18n/messages/pt-BR.ts index 2504570b..0cce9e95 100644 --- a/packages/ui/src/lib/i18n/messages/pt-BR.ts +++ b/packages/ui/src/lib/i18n/messages/pt-BR.ts @@ -954,7 +954,7 @@ export const dict: Record = { "gitView.worktree.availableInWorktreeMode": "Disponível apenas em modo worktree", "contextPanel.mode.chat": "Chat", "contextPanel.mode.files": "Arquivos", - "contextPanel.mode.diff": "Diff", + "contextPanel.mode.diff": "Alterações", "contextPanel.mode.stagedDiff": "Staged Diff", "contextPanel.mode.workingDiff": "Working Diff", "contextPanel.mode.plan": "Plano", @@ -1168,6 +1168,9 @@ export const dict: Record = { "diffView.state.largeDiffDescription": "A renderização pode ser lenta. Você ainda pode ver o diff pelo botão abaixo.", "diffView.summary.changedFilesSingle": "{count} arquivo modificado", "diffView.summary.changedFilesPlural": "{count} arquivos modificados", + "diffView.scope.changed": "Alteradas", + "diffView.scope.staged": "Staged", + "diffView.scope.selectorAria": "Selecionar modo de alterações", "diffView.actions.retry": "Tentar novamente", "diffView.actions.renderAnyway": "Renderizar mesmo assim", "diffView.actions.expandAll": "Expandir tudo", @@ -1264,6 +1267,8 @@ export const dict: Record = { "header.services.modelFamily.other": "Outro", "header.services.shutdownDev": "Parar OpenChamber", "header.actions.openPlanAria": "Abrir plano", + "header.actions.toggleChangesPanel": "Painel de alterações", + "header.actions.toggleChangesPanelAria": "Alternar painel de alterações", "header.actions.planWithShortcut": "Plano ({shortcut})", "header.actions.terminalPanelWithShortcut": "Painel de terminal ({shortcut})", "header.actions.toggleTerminalPanelAria": "Mostrar ou ocultar painel de terminal", diff --git a/packages/ui/src/lib/i18n/messages/uk.ts b/packages/ui/src/lib/i18n/messages/uk.ts index 2c70e8c7..3b201eef 100644 --- a/packages/ui/src/lib/i18n/messages/uk.ts +++ b/packages/ui/src/lib/i18n/messages/uk.ts @@ -954,7 +954,7 @@ export const dict: Record = { "gitView.worktree.availableInWorktreeMode": "Доступно лише в режимі worktree", "contextPanel.mode.chat": "Чат", "contextPanel.mode.files": "Файли", - "contextPanel.mode.diff": "Diff", + "contextPanel.mode.diff": "Зміни", "contextPanel.mode.stagedDiff": "Staged Diff", "contextPanel.mode.workingDiff": "Working Diff", "contextPanel.mode.plan": "План", @@ -1168,6 +1168,9 @@ export const dict: Record = { "diffView.state.largeDiffDescription": "Рендеринг може бути повільним. Ви все одно можете переглянути diff кнопкою нижче.", "diffView.summary.changedFilesSingle": "Змінено файл: {count}", "diffView.summary.changedFilesPlural": "Змінено файлів: {count}", + "diffView.scope.changed": "Змінені", + "diffView.scope.staged": "Індексовані", + "diffView.scope.selectorAria": "Вибрати режим змін", "diffView.actions.retry": "Повторити спробу", "diffView.actions.renderAnyway": "Все одно відрендерити", "diffView.actions.expandAll": "Розгорнути все", @@ -1264,6 +1267,8 @@ export const dict: Record = { "header.services.shutdownDev": "Зупинити OpenChamber", "header.services.modelFamily.other": "інше", "header.actions.openPlanAria": "Відкрити план", + "header.actions.toggleChangesPanel": "Панель змін", + "header.actions.toggleChangesPanelAria": "Перемкнути панель змін", "header.actions.planWithShortcut": "План ({shortcut})", "header.actions.terminalPanelWithShortcut": "Термінальна панель ({shortcut})", "header.actions.toggleTerminalPanelAria": "Перемкнути панель терміналу", diff --git a/packages/ui/src/lib/i18n/messages/zh-CN.ts b/packages/ui/src/lib/i18n/messages/zh-CN.ts index 083937cc..b63d7443 100644 --- a/packages/ui/src/lib/i18n/messages/zh-CN.ts +++ b/packages/ui/src/lib/i18n/messages/zh-CN.ts @@ -954,7 +954,7 @@ export const dict: Record = { 'gitView.worktree.availableInWorktreeMode': '仅在工作树模式下可用', 'contextPanel.mode.chat': '聊天', 'contextPanel.mode.files': '文件', - 'contextPanel.mode.diff': '差异', + "contextPanel.mode.diff": "更改", 'contextPanel.mode.stagedDiff': 'Staged Diff', 'contextPanel.mode.workingDiff': 'Working Diff', 'contextPanel.mode.plan': '计划', @@ -1168,6 +1168,9 @@ export const dict: Record = { 'diffView.state.largeDiffDescription': '渲染可能较慢。你仍可点击下方按钮查看差异。', 'diffView.summary.changedFilesSingle': '{count} 个文件已变更', 'diffView.summary.changedFilesPlural': '{count} 个文件已变更', + "diffView.scope.changed": "已更改", + "diffView.scope.staged": "已暂存", + "diffView.scope.selectorAria": "选择更改模式", 'diffView.actions.retry': '重试', 'diffView.actions.renderAnyway': '仍然渲染', 'diffView.actions.expandAll': '全部展开', @@ -1264,6 +1267,8 @@ export const dict: Record = { 'header.services.shutdownDev': '停止 OpenChamber', 'header.services.modelFamily.other': '其他', 'header.actions.openPlanAria': '打开计划', + "header.actions.toggleChangesPanel": "更改面板", + "header.actions.toggleChangesPanelAria": "切换更改面板", 'header.actions.planWithShortcut': '计划({shortcut})', 'header.actions.terminalPanelWithShortcut': '终端面板({shortcut})', 'header.actions.toggleTerminalPanelAria': '切换终端面板', diff --git a/packages/ui/src/lib/i18n/messages/zh-TW.ts b/packages/ui/src/lib/i18n/messages/zh-TW.ts index d6505b35..344dc9f0 100644 --- a/packages/ui/src/lib/i18n/messages/zh-TW.ts +++ b/packages/ui/src/lib/i18n/messages/zh-TW.ts @@ -966,7 +966,7 @@ export const dict: Record = { 'gitView.worktree.availableInWorktreeMode': '僅在 worktree 模式可用', 'contextPanel.mode.chat': '聊天', 'contextPanel.mode.files': '檔案', - 'contextPanel.mode.diff': '差異', + "contextPanel.mode.diff": "變更", 'contextPanel.mode.stagedDiff': 'Staged Diff', 'contextPanel.mode.workingDiff': 'Working Diff', 'contextPanel.mode.plan': '計畫', @@ -1178,6 +1178,9 @@ export const dict: Record = { 'diffView.state.largeDiffDescription': '渲染可能較慢。你仍可點擊下方按鈕查看差異。', 'diffView.summary.changedFilesSingle': '{count} 個檔案已變更', 'diffView.summary.changedFilesPlural': '{count} 個檔案已變更', + "diffView.scope.changed": "已變更", + "diffView.scope.staged": "已暫存", + "diffView.scope.selectorAria": "選擇變更模式", 'diffView.actions.retry': '重試', 'diffView.actions.renderAnyway': '仍然渲染', 'diffView.actions.expandAll': '全部展開', @@ -1268,6 +1271,8 @@ export const dict: Record = { 'header.services.shutdownDev': '停止 OpenChamber', 'header.services.modelFamily.other': '其他', 'header.actions.openPlanAria': '開啟計畫', + "header.actions.toggleChangesPanel": "變更面板", + "header.actions.toggleChangesPanelAria": "切換變更面板", 'header.actions.planWithShortcut': '計畫({shortcut})', 'header.actions.terminalPanelWithShortcut': '終端機面板({shortcut})', 'header.actions.toggleTerminalPanelAria': '切換終端機面板', diff --git a/packages/ui/src/stores/useUIStore.ts b/packages/ui/src/stores/useUIStore.ts index 2f7f2b2b..22394f42 100644 --- a/packages/ui/src/stores/useUIStore.ts +++ b/packages/ui/src/stores/useUIStore.ts @@ -191,6 +191,10 @@ const normalizeContextPanelTabDedupeKey = ( targetPath: string | null, dedupeKey: string | null | undefined, ): string => { + if (mode === 'diff') { + return mode; + } + if (typeof dedupeKey === 'string') { const trimmed = dedupeKey.trim(); if (trimmed) { @@ -1032,7 +1036,6 @@ export const useUIStore = create()( get().openContextPanelTab(normalizedDirectory, { mode: 'diff', targetPath: normalizedFilePath, - dedupeKey: staged ? 'staged' : null, stagedDiff: staged, }); },