From 905e0495a2129a591e5d92a592c0b1d159174cad Mon Sep 17 00:00:00 2001 From: Kiet Ho Date: Sun, 8 Feb 2026 20:52:32 -0800 Subject: [PATCH] fix(desktop): scope base branch override per workspace The baseBranch in the changes store was a global value shared across all workspaces. When a user changed the base branch comparison in one workspace, it affected every other workspace and persisted across sessions via localStorage. This caused new workspaces to show diff stats and PR info against the wrong branch. Make baseBranch a Record keyed by worktreePath so each workspace maintains its own override. Also fix BaseBranchSelector to reset to null when the default branch is re-selected. --- .../SidebarControl/SidebarControl.tsx | 8 ++---- .../ChangesContent/ChangesContent.tsx | 3 ++- .../RightSidebar/ChangesView/ChangesView.tsx | 3 ++- .../ChangesHeader/ChangesHeader.tsx | 10 ++++--- .../src/renderer/stores/changes/store.ts | 27 +++++++++++++++---- 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/apps/desktop/src/renderer/screens/main/components/SidebarControl/SidebarControl.tsx b/apps/desktop/src/renderer/screens/main/components/SidebarControl/SidebarControl.tsx index 2c2e47ce0db..034c42ec157 100644 --- a/apps/desktop/src/renderer/screens/main/components/SidebarControl/SidebarControl.tsx +++ b/apps/desktop/src/renderer/screens/main/components/SidebarControl/SidebarControl.tsx @@ -25,7 +25,6 @@ const FILE_CATEGORIES: Array<{ export function SidebarControl() { const { isSidebarOpen, toggleSidebar } = useSidebarStore(); - // Get active workspace for file opening const { workspaceId } = useParams({ strict: false }); const { data: workspace } = electronTrpc.workspaces.get.useQuery( { id: workspaceId ?? "" }, @@ -33,21 +32,19 @@ export function SidebarControl() { ); const worktreePath = workspace?.worktreePath; - // Get base branch for changes query - const { baseBranch, selectFile } = useChangesStore(); + const { getBaseBranch, selectFile } = useChangesStore(); + const baseBranch = getBaseBranch(worktreePath || ""); const { data: branchData } = electronTrpc.changes.getBranches.useQuery( { worktreePath: worktreePath || "" }, { enabled: !!worktreePath && !isSidebarOpen }, ); const effectiveBaseBranch = baseBranch ?? branchData?.defaultBranch ?? "main"; - // Get changes status - only query when sidebar is closed (we need it to open first file) const { data: status } = electronTrpc.changes.getStatus.useQuery( { worktreePath: worktreePath || "", defaultBranch: effectiveBaseBranch }, { enabled: !!worktreePath && !isSidebarOpen }, ); - // Access tabs store for file opening const addFileViewerPane = useTabsStore((s) => s.addFileViewerPane); const trpcUtils = electronTrpc.useUtils(); @@ -76,7 +73,6 @@ export function SidebarControl() { const openFirstFile = useCallback(() => { if (!workspaceId || !worktreePath || !status) return; - // Find the first file in priority order let firstFile: ChangedFile | undefined; let category: ChangeCategory | undefined; diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/ChangesContent.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/ChangesContent.tsx index 7a1e6843a63..a412d45d296 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/ChangesContent.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/ChangesContent/ChangesContent.tsx @@ -11,7 +11,8 @@ export function ChangesContent() { ); const worktreePath = workspace?.worktreePath; - const { baseBranch } = useChangesStore(); + const { getBaseBranch } = useChangesStore(); + const baseBranch = getBaseBranch(worktreePath || ""); const { data: branchData } = electronTrpc.changes.getBranches.useQuery( { worktreePath: worktreePath || "" }, { enabled: !!worktreePath }, diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/ChangesView.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/ChangesView.tsx index 7526e8b0d7a..7ed0aeb75e6 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/ChangesView.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/ChangesView.tsx @@ -40,7 +40,8 @@ export function ChangesView({ onFileOpen, isExpandedView }: ChangesViewProps) { ); const worktreePath = workspace?.worktreePath; - const { baseBranch } = useChangesStore(); + const { getBaseBranch } = useChangesStore(); + const baseBranch = getBaseBranch(worktreePath || ""); const { data: branchData } = electronTrpc.changes.getBranches.useQuery( { worktreePath: worktreePath || "" }, { enabled: !!worktreePath }, diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx index ebed41678cb..b56e5b94bc8 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/ChangesHeader.tsx @@ -31,7 +31,8 @@ interface ChangesHeaderProps { } function BaseBranchSelector({ worktreePath }: { worktreePath: string }) { - const { baseBranch, setBaseBranch } = useChangesStore(); + const { getBaseBranch, setBaseBranch } = useChangesStore(); + const baseBranch = getBaseBranch(worktreePath); const { data: branchData, isLoading } = electronTrpc.changes.getBranches.useQuery( { worktreePath }, @@ -46,8 +47,11 @@ function BaseBranchSelector({ worktreePath }: { worktreePath: string }) { }); const handleBranchSelect = (branch: string) => { - if (branch === branchData?.defaultBranch && baseBranch === null) return; - setBaseBranch(branch); + if (branch === branchData?.defaultBranch) { + setBaseBranch(worktreePath, null); + } else { + setBaseBranch(worktreePath, branch); + } }; return ( diff --git a/apps/desktop/src/renderer/stores/changes/store.ts b/apps/desktop/src/renderer/stores/changes/store.ts index f792859bfcb..13017acb41f 100644 --- a/apps/desktop/src/renderer/stores/changes/store.ts +++ b/apps/desktop/src/renderer/stores/changes/store.ts @@ -19,7 +19,7 @@ interface ChangesState { viewMode: DiffViewMode; fileListViewMode: FileListViewMode; expandedSections: Record; - baseBranch: string | null; + baseBranch: Record; showRenderedMarkdown: Record; hideUnchangedRegions: boolean; @@ -34,7 +34,8 @@ interface ChangesState { setFileListViewMode: (mode: FileListViewMode) => void; toggleSection: (section: ChangeCategory) => void; setSectionExpanded: (section: ChangeCategory, expanded: boolean) => void; - setBaseBranch: (branch: string | null) => void; + setBaseBranch: (worktreePath: string, branch: string | null) => void; + getBaseBranch: (worktreePath: string) => string | null; toggleRenderedMarkdown: (worktreePath: string) => void; getShowRenderedMarkdown: (worktreePath: string) => boolean; toggleHideUnchangedRegions: () => void; @@ -51,7 +52,7 @@ const initialState = { staged: true, unstaged: true, }, - baseBranch: null, + baseBranch: {} as Record, showRenderedMarkdown: {} as Record, hideUnchangedRegions: false, }; @@ -110,8 +111,18 @@ export const useChangesStore = create()( }); }, - setBaseBranch: (branch) => { - set({ baseBranch: branch }); + setBaseBranch: (worktreePath, branch) => { + const { baseBranch } = get(); + set({ + baseBranch: { + ...baseBranch, + [worktreePath]: branch, + }, + }); + }, + + getBaseBranch: (worktreePath) => { + return get().baseBranch[worktreePath] ?? null; }, toggleRenderedMarkdown: (worktreePath) => { @@ -144,6 +155,12 @@ export const useChangesStore = create()( }), { name: "changes-store", + version: 1, + migrate: (persisted) => { + const state = persisted as Record; + state.baseBranch = {}; + return state as unknown as ChangesState; + }, partialize: (state) => ({ selectedFiles: state.selectedFiles, viewMode: state.viewMode,