Skip to content
Merged
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
8 changes: 8 additions & 0 deletions src-tauri/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ pub(crate) struct AppSettings {
rename = "notificationSoundsEnabled"
)]
pub(crate) notification_sounds_enabled: bool,
#[serde(default = "default_preload_git_diffs", rename = "preloadGitDiffs")]
pub(crate) preload_git_diffs: bool,
#[serde(
default = "default_experimental_collab_enabled",
rename = "experimentalCollabEnabled"
Expand Down Expand Up @@ -592,6 +594,10 @@ fn default_notification_sounds_enabled() -> bool {
true
}

fn default_preload_git_diffs() -> bool {
true
}

fn default_experimental_collab_enabled() -> bool {
false
}
Expand Down Expand Up @@ -752,6 +758,7 @@ impl Default for AppSettings {
code_font_family: default_code_font_family(),
code_font_size: default_code_font_size(),
notification_sounds_enabled: true,
preload_git_diffs: default_preload_git_diffs(),
experimental_collab_enabled: false,
experimental_collaboration_modes_enabled: false,
experimental_steer_enabled: false,
Expand Down Expand Up @@ -849,6 +856,7 @@ mod tests {
assert!(settings.code_font_family.contains("SF Mono"));
assert_eq!(settings.code_font_size, 11);
assert!(settings.notification_sounds_enabled);
assert!(settings.preload_git_diffs);
assert!(!settings.experimental_steer_enabled);
assert!(!settings.dictation_enabled);
assert_eq!(settings.dictation_model_id, "base");
Expand Down
1 change: 1 addition & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ function MainApp() {
activeWorkspaceRef,
} = useGitPanelController({
activeWorkspace,
gitDiffPreloadEnabled: appSettings.preloadGitDiffs,
isCompact,
isTablet,
activeTab,
Expand Down
130 changes: 130 additions & 0 deletions src/features/app/hooks/useGitPanelController.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// @vitest-environment jsdom
import { act, renderHook } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { WorkspaceInfo } from "../../../types";
import { useGitPanelController } from "./useGitPanelController";

const useGitDiffsMock = vi.fn();
const useGitStatusMock = vi.fn();
const useGitLogMock = vi.fn();
const useGitCommitDiffsMock = vi.fn();

vi.mock("../../git/hooks/useGitDiffs", () => ({
useGitDiffs: (...args: unknown[]) => useGitDiffsMock(...args),
}));

vi.mock("../../git/hooks/useGitStatus", () => ({
useGitStatus: (...args: unknown[]) => useGitStatusMock(...args),
}));

vi.mock("../../git/hooks/useGitLog", () => ({
useGitLog: (...args: unknown[]) => useGitLogMock(...args),
}));

vi.mock("../../git/hooks/useGitCommitDiffs", () => ({
useGitCommitDiffs: (...args: unknown[]) => useGitCommitDiffsMock(...args),
}));

const workspace: WorkspaceInfo = {
id: "workspace-1",
name: "CodexMonitor",
path: "/tmp/codex-monitor",
connected: true,
settings: { sidebarCollapsed: false },
};

function makeProps(overrides?: Partial<Parameters<typeof useGitPanelController>[0]>) {
return {
activeWorkspace: workspace,
gitDiffPreloadEnabled: false,
isCompact: false,
isTablet: false,
activeTab: "codex" as const,
tabletTab: "codex" as const,
setActiveTab: vi.fn(),
prDiffs: [],
prDiffsLoading: false,
prDiffsError: null,
...overrides,
};
}

function getLastEnabledArg() {
const { calls } = useGitDiffsMock.mock;
if (calls.length === 0) {
return undefined;
}
return calls[calls.length - 1]?.[2];
}

beforeEach(() => {
useGitStatusMock.mockReturnValue({
status: {
branchName: "main",
files: [],
stagedFiles: [],
unstagedFiles: [],
totalAdditions: 0,
totalDeletions: 0,
},
refresh: vi.fn(),
});
useGitDiffsMock.mockReturnValue({
diffs: [],
isLoading: false,
error: null,
refresh: vi.fn(),
});
useGitLogMock.mockReturnValue({
entries: [],
total: 0,
ahead: 0,
behind: 0,
aheadEntries: [],
behindEntries: [],
upstream: null,
isLoading: false,
error: null,
refresh: vi.fn(),
});
useGitCommitDiffsMock.mockReturnValue({
diffs: [],
isLoading: false,
error: null,
});
useGitDiffsMock.mockClear();
});

describe("useGitPanelController preload behavior", () => {
it("does not preload diffs when disabled and panel is hidden", () => {
const { result } = renderHook(() => useGitPanelController(makeProps()));

const initialEnabled = getLastEnabledArg();
expect(initialEnabled).toBe(true);

act(() => {
result.current.setGitPanelMode("issues");
});

const lastEnabled = getLastEnabledArg();
expect(lastEnabled).toBe(false);
});

it("loads diffs when the panel becomes visible even if preload is disabled", () => {
const { result } = renderHook(() => useGitPanelController(makeProps()));

act(() => {
result.current.setGitPanelMode("issues");
});

const hiddenEnabled = getLastEnabledArg();
expect(hiddenEnabled).toBe(false);

act(() => {
result.current.setGitPanelMode("diff");
});

const visibleEnabled = getLastEnabledArg();
expect(visibleEnabled).toBe(true);
});
});
16 changes: 13 additions & 3 deletions src/features/app/hooks/useGitPanelController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useGitCommitDiffs } from "../../git/hooks/useGitCommitDiffs";

export function useGitPanelController({
activeWorkspace,
gitDiffPreloadEnabled,
isCompact,
isTablet,
activeTab,
Expand All @@ -17,6 +18,7 @@ export function useGitPanelController({
prDiffsError,
}: {
activeWorkspace: WorkspaceInfo | null;
gitDiffPreloadEnabled: boolean;
isCompact: boolean;
isTablet: boolean;
activeTab: "projects" | "codex" | "git" | "log";
Expand Down Expand Up @@ -94,18 +96,26 @@ export function useGitPanelController({
centerMode === "diff" ||
(isCompact ? compactTab === "git" : gitPanelMode === "diff");
const shouldPreloadDiffs = Boolean(
activeWorkspace && !preloadedWorkspaceIdsRef.current.has(activeWorkspace.id),
gitDiffPreloadEnabled &&
activeWorkspace &&
!preloadedWorkspaceIdsRef.current.has(activeWorkspace.id),
);
const shouldLoadLocalDiffs =
Boolean(activeWorkspace) &&
(shouldPreloadDiffs ||
diffUiVisible ||
Boolean(selectedDiffPath));
const shouldLoadDiffs =
Boolean(activeWorkspace) && (diffUiVisible || shouldPreloadDiffs);
Boolean(activeWorkspace) &&
(diffSource === "local" ? shouldLoadLocalDiffs : diffUiVisible);
const shouldLoadGitLog = gitPanelMode === "log" && Boolean(activeWorkspace);

const {
diffs: gitDiffs,
isLoading: isDiffLoading,
error: diffError,
refresh: refreshGitDiffs,
} = useGitDiffs(activeWorkspace, gitStatus.files, shouldLoadDiffs);
} = useGitDiffs(activeWorkspace, gitStatus.files, shouldLoadLocalDiffs);

useEffect(() => {
if (!activeWorkspace || !shouldPreloadDiffs) {
Expand Down
1 change: 1 addition & 0 deletions src/features/app/hooks/useSettingsModalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type SettingsSection =
| "dictation"
| "shortcuts"
| "open-apps"
| "git"
| "codex"
| "experimental";

Expand Down
1 change: 1 addition & 0 deletions src/features/settings/components/SettingsView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const baseSettings: AppSettings = {
"\"SF Mono\", \"SFMono-Regular\", Menlo, Monaco, monospace",
codeFontSize: 11,
notificationSoundsEnabled: true,
preloadGitDiffs: true,
experimentalCollabEnabled: false,
experimentalCollaborationModesEnabled: false,
experimentalSteerEnabled: false,
Expand Down
41 changes: 40 additions & 1 deletion src/features/settings/components/SettingsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import SlidersHorizontal from "lucide-react/dist/esm/icons/sliders-horizontal";
import Mic from "lucide-react/dist/esm/icons/mic";
import Keyboard from "lucide-react/dist/esm/icons/keyboard";
import Stethoscope from "lucide-react/dist/esm/icons/stethoscope";
import GitBranch from "lucide-react/dist/esm/icons/git-branch";
import TerminalSquare from "lucide-react/dist/esm/icons/terminal-square";
import FileText from "lucide-react/dist/esm/icons/file-text";
import Trash2 from "lucide-react/dist/esm/icons/trash-2";
Expand Down Expand Up @@ -174,7 +175,8 @@ type SettingsSection =
| "composer"
| "dictation"
| "shortcuts"
| "open-apps";
| "open-apps"
| "git";
type CodexSection = SettingsSection | "codex" | "experimental";
type ShortcutSettingKey =
| "composerModelShortcut"
Expand Down Expand Up @@ -1036,6 +1038,14 @@ export function SettingsView({
<ExternalLink aria-hidden />
Open in
</button>
<button
type="button"
className={`settings-nav ${activeSection === "git" ? "active" : ""}`}
onClick={() => setActiveSection("git")}
>
<GitBranch aria-hidden />
Git
</button>
<button
type="button"
className={`settings-nav ${activeSection === "codex" ? "active" : ""}`}
Expand Down Expand Up @@ -2556,6 +2566,35 @@ export function SettingsView({
</div>
</section>
)}
{activeSection === "git" && (
<section className="settings-section">
<div className="settings-section-title">Git</div>
<div className="settings-section-subtitle">
Manage how diffs are loaded in the Git sidebar.
</div>
<div className="settings-toggle-row">
<div>
<div className="settings-toggle-title">Preload git diffs</div>
<div className="settings-toggle-subtitle">
Make viewing git diff faster.
</div>
</div>
<button
type="button"
className={`settings-toggle ${appSettings.preloadGitDiffs ? "on" : ""}`}
onClick={() =>
void onUpdateAppSettings({
...appSettings,
preloadGitDiffs: !appSettings.preloadGitDiffs,
})
}
aria-pressed={appSettings.preloadGitDiffs}
>
<span className="settings-toggle-knob" />
</button>
</div>
</section>
)}
{activeSection === "codex" && (
<section className="settings-section">
<div className="settings-section-title">Codex</div>
Expand Down
1 change: 1 addition & 0 deletions src/features/settings/hooks/useAppSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const defaultSettings: AppSettings = {
codeFontFamily: DEFAULT_CODE_FONT_FAMILY,
codeFontSize: CODE_FONT_SIZE_DEFAULT,
notificationSoundsEnabled: true,
preloadGitDiffs: true,
experimentalCollabEnabled: false,
experimentalCollaborationModesEnabled: false,
experimentalSteerEnabled: false,
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export type AppSettings = {
codeFontFamily: string;
codeFontSize: number;
notificationSoundsEnabled: boolean;
preloadGitDiffs: boolean;
experimentalCollabEnabled: boolean;
experimentalCollaborationModesEnabled: boolean;
experimentalSteerEnabled: boolean;
Expand Down