fix: resolve sidebar stale state after worktree, folder, project, and session mutations (#1038)

* fix: update sidebar store after worktree creation

* fix: update sidebar store after worktree removal

* fix: update sidebar store with correct key in removeProjectWorktree

- Fixed key mismatch in sidebar store updates for worktree removal
- Removed worktrees now properly disappear from sidebar
- Aligned remove path with create path key resolution

* fix: resolve sidebar stale state after folder, worktree, project, and session mutations

* fix: now builds

* Fix worktree sidebar store key

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
Islam Nofl
2026-04-27 13:42:52 +03:00
committed by GitHub
co-authored by Bohdan Triapitsyn
parent b62faadd15
commit 8fdc1e7e55
8 changed files with 94 additions and 18 deletions
@@ -13,6 +13,7 @@ import type {
CreateGitWorktreePayload,
GitWorktreeValidationResult,
} from '@/lib/api/types';
import { useSessionUIStore } from '@/sync/session-ui-store';
type WorktreeListEntry = {
path?: string;
@@ -316,6 +317,17 @@ export async function createWorktree(project: ProjectRef, args: CreateWorktreeAr
_worktreeListCache.delete(projectDirectory);
// Update sidebar store so new worktree appears immediately
const sidebarProjectKey = projectDirectory;
const currentByProject = useSessionUIStore.getState().availableWorktreesByProject;
const updatedByProject = new Map(currentByProject);
const existing = updatedByProject.get(sidebarProjectKey) ?? [];
updatedByProject.set(sidebarProjectKey, [...existing, metadata]);
useSessionUIStore.setState({
availableWorktreesByProject: updatedByProject,
availableWorktrees: [...useSessionUIStore.getState().availableWorktrees, metadata],
});
return metadata;
}
@@ -330,7 +342,7 @@ export async function removeProjectWorktree(project: ProjectRef, worktree: Workt
deleteLocalBranch?: boolean;
remoteName?: string;
}): Promise<void> {
const projectDirectory = project.path;
const projectDirectory = normalizePath(project.path);
const deleteRemote = Boolean(options?.deleteRemoteBranch);
const deleteLocalBranch = options?.deleteLocalBranch === true;
@@ -347,6 +359,34 @@ export async function removeProjectWorktree(project: ProjectRef, worktree: Workt
_worktreeListCache.delete(normalizePath(project.path));
// Update sidebar store so removed worktree disappears immediately
const normalizedWorktreePath = normalizePath(worktree.path);
const sidebarProjectKey = projectDirectory;
const currentByProject = useSessionUIStore.getState().availableWorktreesByProject;
const updatedByProject = new Map(currentByProject);
const projectWorktrees = updatedByProject.get(sidebarProjectKey) ?? [];
updatedByProject.set(
sidebarProjectKey,
projectWorktrees.filter((w) => normalizePath(w.path) !== normalizedWorktreePath),
);
// Clean up worktreeMetadata for sessions in the removed worktree
const currentMetadata = useSessionUIStore.getState().worktreeMetadata;
const updatedMetadata = new Map(currentMetadata);
for (const [sid, meta] of currentMetadata.entries()) {
if (meta && normalizePath(meta.path) === normalizedWorktreePath) {
updatedMetadata.delete(sid);
}
}
useSessionUIStore.setState({
availableWorktreesByProject: updatedByProject,
availableWorktrees: useSessionUIStore.getState().availableWorktrees.filter(
(w) => normalizePath(w.path) !== normalizedWorktreePath,
),
worktreeMetadata: updatedMetadata,
});
const branchName = (worktree.branch || '').replace(/^refs\/heads\//, '').trim();
if (deleteRemote && branchName) {
await deleteRemoteBranch(projectDirectory, { branch: branchName, remote: remoteName }).catch(() => undefined);