From 17f1edf2d99418505b09397e4f29df4be67a67cd Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Fri, 29 May 2026 07:38:45 -0700 Subject: [PATCH] Keep main workspace first in project groups --- .../sidebar/worktree-list-groups.test.ts | 33 +++++++++++++++++++ .../sidebar/worktree-list-groups.ts | 13 +++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/renderer/src/components/sidebar/worktree-list-groups.test.ts b/src/renderer/src/components/sidebar/worktree-list-groups.test.ts index a002c9211bd..ee88f09dbca 100644 --- a/src/renderer/src/components/sidebar/worktree-list-groups.test.ts +++ b/src/renderer/src/components/sidebar/worktree-list-groups.test.ts @@ -395,6 +395,39 @@ describe('buildRows project grouping order', () => { ]) }) + it('keeps the main workspace first inside its project group', () => { + const main = { + ...wA, + id: 'wt-a-main', + displayName: 'main', + isMainWorktree: true + } + const freshChild = { + ...wA, + id: 'wt-a-fresh-child', + displayName: 'fresh-child', + isMainWorktree: false + } + const rows = buildRows( + 'repo', + [freshChild, wB, main], + map, + null, + new Set(), + undefined, + undefined, + 'visible-worktree-order' + ) + + expect(rows).toMatchObject([ + { type: 'header', key: 'repo:repo-a' }, + { type: 'item', worktree: { id: 'wt-a-main' } }, + { type: 'item', worktree: { id: 'wt-a-fresh-child' } }, + { type: 'header', key: 'repo:repo-b' }, + { type: 'item', worktree: { id: 'wt-b' } } + ]) + }) + it('keeps repoOrder for manual project group ordering', () => { const repoOrder = new Map([ [repoB.id, 0], diff --git a/src/renderer/src/components/sidebar/worktree-list-groups.ts b/src/renderer/src/components/sidebar/worktree-list-groups.ts index 6cb30380dca..019a1c2718a 100644 --- a/src/renderer/src/components/sidebar/worktree-list-groups.ts +++ b/src/renderer/src/components/sidebar/worktree-list-groups.ts @@ -344,6 +344,16 @@ function appendWorktreeRows( } } +function orderMainWorktreeFirst(worktrees: Worktree[]): Worktree[] { + const mainWorktrees = worktrees.filter((worktree) => worktree.isMainWorktree) + if (mainWorktrees.length === 0) { + return worktrees + } + // Why: project groups are scanned by repo; keep the repo's canonical + // workspace anchored even when dynamic sorts rank a child workspace first. + return [...mainWorktrees, ...worktrees.filter((worktree) => !worktree.isMainWorktree)] +} + /** * Build the flat row list consumed by the virtualizer. * Extracted here to keep WorktreeList.tsx under the line-count lint limit. @@ -527,7 +537,8 @@ export function buildRows( result.push(header) if (!isCollapsed) { - appendWorktreeRows(result, group.items, repoMap, lineageById, worktreeMap, { + const items = groupBy === 'repo' ? orderMainWorktreeFirst(group.items) : group.items + appendWorktreeRows(result, items, repoMap, lineageById, worktreeMap, { nestLineage, collapsedGroups })