diff --git a/src/main/settings.ts b/src/main/settings.ts
index 82cd0cc3d..8f24c92cf 100644
--- a/src/main/settings.ts
+++ b/src/main/settings.ts
@@ -70,6 +70,7 @@ export interface InterfaceSettings {
showResourceMonitor?: boolean;
theme?: 'light' | 'dark' | 'dark-black' | 'system';
taskHoverAction?: 'delete' | 'archive';
+ expandCommitDetail?: boolean;
}
/**
@@ -205,6 +206,7 @@ const DEFAULT_SETTINGS: AppSettings = {
showResourceMonitor: false,
theme: 'system',
taskHoverAction: 'delete',
+ expandCommitDetail: false,
},
providerConfigs: {},
terminal: {
@@ -549,6 +551,9 @@ export function normalizeSettings(input: AppSettings): AppSettings {
? iface.theme
: DEFAULT_SETTINGS.interface!.theme,
taskHoverAction: iface?.taskHoverAction === 'archive' ? 'archive' : 'delete',
+ expandCommitDetail: Boolean(
+ iface?.expandCommitDetail ?? DEFAULT_SETTINGS.interface!.expandCommitDetail
+ ),
};
// Provider custom configs
diff --git a/src/renderer/components/CommitDetailSettingsCard.tsx b/src/renderer/components/CommitDetailSettingsCard.tsx
new file mode 100644
index 000000000..8a051e9bc
--- /dev/null
+++ b/src/renderer/components/CommitDetailSettingsCard.tsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import { Switch } from './ui/switch';
+import { useAppSettings } from '@/contexts/AppSettingsProvider';
+
+const CommitDetailSettingsCard: React.FC = () => {
+ const { settings, updateSettings, isLoading: loading } = useAppSettings();
+
+ const expandCommitDetail = settings?.interface?.expandCommitDetail ?? false;
+
+ return (
+
+
+
+ Expand commit details by default
+
+
+ Automatically show the full commit message and author when selecting a commit in the
+ History tab
+
+
+
+ updateSettings({ interface: { expandCommitDetail: checked } })
+ }
+ />
+
+ );
+};
+
+export default CommitDetailSettingsCard;
diff --git a/src/renderer/components/SettingsPage.tsx b/src/renderer/components/SettingsPage.tsx
index 293cb280d..8fd3e142b 100644
--- a/src/renderer/components/SettingsPage.tsx
+++ b/src/renderer/components/SettingsPage.tsx
@@ -28,6 +28,7 @@ import TerminalSettingsCard from './TerminalSettingsCard';
import HiddenToolsSettingsCard from './HiddenToolsSettingsCard';
import ReviewAgentSettingsCard from './ReviewAgentSettingsCard';
import ResourceMonitorSettingsCard from './ResourceMonitorSettingsCard';
+import CommitDetailSettingsCard from './CommitDetailSettingsCard';
import { AccountTab } from './settings/AccountTab';
import { WorkspaceProviderInfoCard } from './WorkspaceProviderInfoCard';
import { useTaskSettings } from '../hooks/useTaskSettings';
@@ -268,6 +269,7 @@ export const SettingsPage: React.FC = ({ initialTab, onClose
+
),
},
diff --git a/src/renderer/components/diff-viewer/HistoryTab.tsx b/src/renderer/components/diff-viewer/HistoryTab.tsx
index d6c65a634..271ee1116 100644
--- a/src/renderer/components/diff-viewer/HistoryTab.tsx
+++ b/src/renderer/components/diff-viewer/HistoryTab.tsx
@@ -6,6 +6,8 @@ import { CommitFileList } from './CommitFileList';
import { CommitFileDiffView } from './CommitFileDiffView';
import { DiffToolbar } from './DiffToolbar';
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '../ui/resizable';
+import { useAppSettings } from '@/contexts/AppSettingsProvider';
+import { cn } from '@/lib/utils';
interface HistoryTabProps {
taskPath?: string;
@@ -27,6 +29,8 @@ export const HistoryTab: React.FC = ({
const [diffStyle, setDiffStyle] = useState<'unified' | 'split'>(
() => (localStorage.getItem('diffViewer:diffStyle') as 'unified' | 'split') || 'unified'
);
+ const { settings } = useAppSettings();
+ const expandByDefault = settings?.interface?.expandCommitDetail ?? false;
const [detailExpanded, setDetailExpanded] = useState(false);
const [copied, setCopied] = useState(false);
@@ -39,7 +43,7 @@ export const HistoryTab: React.FC = ({
if (commit.hash === selectedCommit?.hash) return;
setSelectedCommit(commit);
setSelectedFile(null);
- setDetailExpanded(false);
+ setDetailExpanded(expandByDefault);
setCopied(false);
};
@@ -99,7 +103,12 @@ export const HistoryTab: React.FC = ({
{/* Commit message detail */}
-
+
{selectedCommit.subject}
{hasExpandableContent && (
diff --git a/src/test/main/settings.test.ts b/src/test/main/settings.test.ts
index 5456eeab2..0463f7c33 100644
--- a/src/test/main/settings.test.ts
+++ b/src/test/main/settings.test.ts
@@ -283,3 +283,25 @@ describe('normalizeSettings – terminal settings', () => {
expect(result.terminal?.macOptionIsMeta).toBe(true);
});
});
+
+describe('normalizeSettings – expandCommitDetail', () => {
+ it('defaults expandCommitDetail to false when not set', () => {
+ const result = normalizeSettings(makeSettings());
+ expect(result.interface?.expandCommitDetail).toBe(false);
+ });
+
+ it('preserves expandCommitDetail: true', () => {
+ const result = normalizeSettings(makeSettings({ interface: { expandCommitDetail: true } }));
+ expect(result.interface?.expandCommitDetail).toBe(true);
+ });
+
+ it('preserves expandCommitDetail: false', () => {
+ const result = normalizeSettings(makeSettings({ interface: { expandCommitDetail: false } }));
+ expect(result.interface?.expandCommitDetail).toBe(false);
+ });
+
+ it('coerces missing value inside interface to false', () => {
+ const result = normalizeSettings(makeSettings({ interface: {} }));
+ expect(result.interface?.expandCommitDetail).toBe(false);
+ });
+});
diff --git a/src/test/renderer/CommitDetailSettingsCard.component.test.tsx b/src/test/renderer/CommitDetailSettingsCard.component.test.tsx
new file mode 100644
index 000000000..b620ce7dc
--- /dev/null
+++ b/src/test/renderer/CommitDetailSettingsCard.component.test.tsx
@@ -0,0 +1,51 @@
+import { render, screen, fireEvent } from '@testing-library/react';
+import { describe, expect, it, vi } from 'vitest';
+import { useAppSettings } from '@/contexts/AppSettingsProvider';
+import CommitDetailSettingsCard from '../../renderer/components/CommitDetailSettingsCard';
+
+vi.mock('@/contexts/AppSettingsProvider', () => ({
+ useAppSettings: vi.fn(),
+}));
+
+function setup(expandCommitDetail = false) {
+ const updateSettings = vi.fn();
+ vi.mocked(useAppSettings).mockReturnValue({
+ settings: {
+ interface: { expandCommitDetail },
+ } as unknown as ReturnType
['settings'],
+ isLoading: false,
+ isSaving: false,
+ updateSettings,
+ });
+ render();
+ return { updateSettings };
+}
+
+describe('CommitDetailSettingsCard', () => {
+ it('renders the toggle label', () => {
+ setup();
+ expect(screen.getByText('Expand commit details by default')).toBeInTheDocument();
+ });
+
+ it('is unchecked when expandCommitDetail is false', () => {
+ setup(false);
+ expect(screen.getByRole('switch')).toHaveAttribute('data-state', 'unchecked');
+ });
+
+ it('is checked when expandCommitDetail is true', () => {
+ setup(true);
+ expect(screen.getByRole('switch')).toHaveAttribute('data-state', 'checked');
+ });
+
+ it('calls updateSettings with true when toggled on', () => {
+ const { updateSettings } = setup(false);
+ fireEvent.click(screen.getByRole('switch'));
+ expect(updateSettings).toHaveBeenCalledWith({ interface: { expandCommitDetail: true } });
+ });
+
+ it('calls updateSettings with false when toggled off', () => {
+ const { updateSettings } = setup(true);
+ fireEvent.click(screen.getByRole('switch'));
+ expect(updateSettings).toHaveBeenCalledWith({ interface: { expandCommitDetail: false } });
+ });
+});