Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/main/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export interface InterfaceSettings {
showResourceMonitor?: boolean;
theme?: 'light' | 'dark' | 'dark-black' | 'system';
taskHoverAction?: 'delete' | 'archive';
expandCommitDetail?: boolean;
}

/**
Expand Down Expand Up @@ -205,6 +206,7 @@ const DEFAULT_SETTINGS: AppSettings = {
showResourceMonitor: false,
theme: 'system',
taskHoverAction: 'delete',
expandCommitDetail: false,
},
providerConfigs: {},
terminal: {
Expand Down Expand Up @@ -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
Expand Down
32 changes: 32 additions & 0 deletions src/renderer/components/CommitDetailSettingsCard.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="flex items-center justify-between gap-4">
<div className="flex flex-1 flex-col gap-0.5">
<span className="text-sm font-medium text-foreground">
Expand commit details by default
</span>
<span className="text-sm text-muted-foreground">
Automatically show the full commit message and author when selecting a commit in the
History tab
</span>
</div>
<Switch
checked={expandCommitDetail}
disabled={loading}
onCheckedChange={(checked) =>
updateSettings({ interface: { expandCommitDetail: checked } })
}
/>
</div>
);
};

export default CommitDetailSettingsCard;
2 changes: 2 additions & 0 deletions src/renderer/components/SettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -268,6 +269,7 @@ export const SettingsPage: React.FC<SettingsPageProps> = ({ initialTab, onClose
<RightSidebarSettingsCard />
<BrowserPreviewSettingsCard />
<TaskHoverActionCard />
<CommitDetailSettingsCard />
</div>
),
},
Expand Down
13 changes: 11 additions & 2 deletions src/renderer/components/diff-viewer/HistoryTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,6 +29,8 @@ export const HistoryTab: React.FC<HistoryTabProps> = ({
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);

Expand All @@ -39,7 +43,7 @@ export const HistoryTab: React.FC<HistoryTabProps> = ({
if (commit.hash === selectedCommit?.hash) return;
setSelectedCommit(commit);
setSelectedFile(null);
setDetailExpanded(false);
setDetailExpanded(expandByDefault);
setCopied(false);
};

Expand Down Expand Up @@ -99,7 +103,12 @@ export const HistoryTab: React.FC<HistoryTabProps> = ({
{/* Commit message detail */}
<div className="border-b border-border px-3 py-2">
<div className="flex items-center gap-1">
<div className="min-w-0 flex-1 truncate text-sm font-medium leading-snug">
<div
className={cn(
'min-w-0 flex-1 text-sm font-medium leading-snug',
!detailExpanded && 'truncate'
)}
>
{selectedCommit.subject}
</div>
{hasExpandableContent && (
Expand Down
22 changes: 22 additions & 0 deletions src/test/main/settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
51 changes: 51 additions & 0 deletions src/test/renderer/CommitDetailSettingsCard.component.test.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof useAppSettings>['settings'],
isLoading: false,
isSaving: false,
updateSettings,
});
render(<CommitDetailSettingsCard />);
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 } });
});
});
Loading