Remove child workspace nesting toggle (#2168)

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Brennan Benson 2026-05-17 15:34:27 -07:00 committed by GitHub
parent 231bad8e19
commit c916218d85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 11 additions and 48 deletions

View File

@ -338,7 +338,6 @@ function App(): React.JSX.Element {
const sidebarWidth = useAppStore((s) => s.sidebarWidth)
const sidebarOpen = useAppStore((s) => s.sidebarOpen)
const groupBy = useAppStore((s) => s.groupBy)
const showWorkspaceLineage = useAppStore((s) => s.showWorkspaceLineage)
const sortBy = useAppStore((s) => s.sortBy)
const showActiveOnly = useAppStore((s) => s.showActiveOnly)
const hideDefaultBranchWorkspace = useAppStore((s) => s.hideDefaultBranchWorkspace)
@ -810,7 +809,6 @@ function App(): React.JSX.Element {
sidebarWidth,
rightSidebarWidth,
groupBy,
showWorkspaceLineage,
sortBy,
showActiveOnly,
hideDefaultBranchWorkspace,
@ -830,7 +828,6 @@ function App(): React.JSX.Element {
sidebarWidth,
rightSidebarWidth,
groupBy,
showWorkspaceLineage,
sortBy,
showActiveOnly,
hideDefaultBranchWorkspace,

View File

@ -66,8 +66,6 @@ const SidebarHeader = React.memo(function SidebarHeader() {
const setSortBy = useAppStore((s) => s.setSortBy)
const groupBy = useAppStore((s) => s.groupBy)
const setGroupBy = useAppStore((s) => s.setGroupBy)
const showWorkspaceLineage = useAppStore((s) => s.showWorkspaceLineage)
const setShowWorkspaceLineage = useAppStore((s) => s.setShowWorkspaceLineage)
const handleWorkspaceBoardOpenChange = useCallback((open: boolean) => {
setWorkspaceBoardOpen(open)
@ -195,15 +193,6 @@ const SidebarHeader = React.memo(function SidebarHeader() {
</ToggleGroup>
</div>
<DropdownMenuSeparator />
<DropdownMenuCheckboxItem
checked={showWorkspaceLineage}
onCheckedChange={(checked) => setShowWorkspaceLineage(Boolean(checked))}
onSelect={(e) => e.preventDefault()}
>
Nest child workspaces
</DropdownMenuCheckboxItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>Sort by</DropdownMenuLabel>
<DropdownMenuRadioGroup

View File

@ -655,7 +655,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
</div>
)}
{lineageChildren && <div className="-ml-4 mt-1.5 space-y-1">{lineageChildren}</div>}
{lineageChildren && <div className="-ml-3 mt-1.5 space-y-1">{lineageChildren}</div>}
</div>
</div>
)

View File

@ -121,13 +121,12 @@ function getWorktreeOptionId(worktreeId: string): string {
return `worktree-list-option-${encodeURIComponent(worktreeId)}`
}
const LINEAGE_INDENT = 24
const LINEAGE_INDENT = 18
type VirtualizedWorktreeViewportProps = {
rows: Row[]
activeWorktreeId: string | null
groupBy: WorktreeGroupBy
showWorkspaceLineage: boolean
showInlineAgentCards: boolean
repoGroupOrdering: RepoGroupOrdering
toggleGroup: (key: string) => void
@ -185,11 +184,7 @@ function renderRowContainsWorktree(row: RenderRow, worktreeId: string | null): b
return row.type === 'item' && row.worktree.id === worktreeId
}
function buildRenderableRows(rows: Row[], showWorkspaceLineage: boolean): RenderRow[] {
if (!showWorkspaceLineage) {
return rows
}
function buildRenderableRows(rows: Row[]): RenderRow[] {
const renderRows: RenderRow[] = []
for (let index = 0; index < rows.length; index++) {
const row = rows[index]
@ -258,7 +253,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
rows,
activeWorktreeId,
groupBy,
showWorkspaceLineage,
showInlineAgentCards,
repoGroupOrdering,
toggleGroup,
@ -300,10 +294,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
onCommit: reorderRepos,
getScrollContainer: () => scrollRef.current
})
const renderRows = useMemo(
() => buildRenderableRows(rows, showWorkspaceLineage),
[rows, showWorkspaceLineage]
)
const renderRows = useMemo(() => buildRenderableRows(rows), [rows])
const activeWorktreeRowIndex = useMemo(
() => renderRows.findIndex((row) => renderRowContainsWorktree(row, activeWorktreeId)),
[renderRows, activeWorktreeId]
@ -386,7 +377,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
{
const targetWorktree = worktrees.find((w) => w.id === pendingRevealWorktreeId)
if (targetWorktree && showWorkspaceLineage && !targetWorktree.isPinned) {
if (targetWorktree && !targetWorktree.isPinned) {
const seen = new Set<string>()
let current: Worktree | undefined = targetWorktree
while (current && !seen.has(current.id)) {
@ -454,7 +445,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
prCache,
worktreeLineageById,
worktreeMap,
showWorkspaceLineage,
renderRows,
virtualizer,
clearPendingRevealWorktreeId,
@ -545,7 +535,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
repoGroupOrdering,
worktreeLineageById,
worktreeMap,
showWorkspaceLineage
true
).filter((r): r is Extract<Row, { type: 'item' }> => r.type === 'item')
if (worktreeRows.length === 0) {
return
@ -590,8 +580,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
repoOrder,
workspaceStatuses,
worktreeLineageById,
worktreeMap,
showWorkspaceLineage
worktreeMap
]
)
@ -1213,7 +1202,6 @@ const WorktreeList = React.memo(function WorktreeList({
const worktreesByRepo = useAppStore((s) => s.worktreesByRepo)
const activeWorktreeId = useAppStore((s) => s.activeWorktreeId)
const groupBy = useAppStore((s) => s.groupBy)
const showWorkspaceLineage = useAppStore((s) => s.showWorkspaceLineage)
const workspaceStatuses = useAppStore((s) => s.workspaceStatuses)
const sortBy = useAppStore((s) => s.sortBy)
const showActiveOnly = useAppStore((s) => s.showActiveOnly)
@ -1539,7 +1527,7 @@ const WorktreeList = React.memo(function WorktreeList({
repoGroupOrdering,
worktreeLineageById,
worktreeMap,
showWorkspaceLineage
true
),
[
groupBy,
@ -1551,8 +1539,7 @@ const WorktreeList = React.memo(function WorktreeList({
workspaceStatuses,
repoGroupOrdering,
worktreeLineageById,
worktreeMap,
showWorkspaceLineage
worktreeMap
]
)
// Why: header/mode changes can shift entire groups, so remount the
@ -1564,8 +1551,8 @@ const WorktreeList = React.memo(function WorktreeList({
.filter((r): r is GroupHeaderRow => r.type === 'header')
.map((r) => r.key)
.join(',')
return `${groupBy}:${showWorkspaceLineage ? 'lineage' : 'flat'}:${headers}`
}, [groupBy, rows, showWorkspaceLineage])
return `${groupBy}:lineage:${headers}`
}, [groupBy, rows])
// Why: derive the rendered item order from the post-buildRows() row list,
// not the flat `worktrees` array, because grouping (groupBy: 'repo' or
@ -1795,7 +1782,6 @@ const WorktreeList = React.memo(function WorktreeList({
rows={rows}
activeWorktreeId={selectedSidebarWorktreeId}
groupBy={groupBy}
showWorkspaceLineage={showWorkspaceLineage}
showInlineAgentCards={cardProps.includes('inline-agents')}
repoGroupOrdering={repoGroupOrdering}
toggleGroup={toggleGroup}

View File

@ -35,7 +35,6 @@ export function getStartupErrorFallbackUI(uiHydrated: boolean): PersistedUIState
sidebarWidth: 280,
rightSidebarWidth: 350,
groupBy: 'repo',
showWorkspaceLineage: false,
sortBy: 'name',
showActiveOnly: false,
hideDefaultBranchWorkspace: false,

View File

@ -354,8 +354,6 @@ export type UISlice = {
clearOrcaHookTrustForRepo: (repoId: string) => void
groupBy: 'none' | 'workspace-status' | 'repo' | 'pr-status'
setGroupBy: (g: UISlice['groupBy']) => void
showWorkspaceLineage: boolean
setShowWorkspaceLineage: (v: boolean) => void
sortBy: 'name' | 'smart' | 'recent' | 'repo'
setSortBy: (s: UISlice['sortBy']) => void
showActiveOnly: boolean
@ -723,9 +721,6 @@ export const createUISlice: StateCreator<AppState, [], [], UISlice> = (set, get)
set({ groupBy: g, collapsedGroups: new Set<string>() })
},
showWorkspaceLineage: false,
setShowWorkspaceLineage: (v) => set({ showWorkspaceLineage: v }),
sortBy: 'recent',
setSortBy: (s) => set({ sortBy: s }),
@ -918,7 +913,6 @@ export const createUISlice: StateCreator<AppState, [], [], UISlice> = (set, get)
MAX_RIGHT_SIDEBAR_WIDTH
),
groupBy: (ui.groupBy as UISlice['groupBy'] | 'parent') === 'parent' ? 'repo' : ui.groupBy,
showWorkspaceLineage: ui.showWorkspaceLineage ?? false,
sortBy,
// Why: "Active only" is part of the user's sidebar working set, not a
// transient render detail. Restoring it on launch keeps the filtered

View File

@ -341,7 +341,6 @@ export function getDefaultUIState(): PersistedUIState {
sidebarWidth: 280,
rightSidebarWidth: 350,
groupBy: 'repo',
showWorkspaceLineage: false,
sortBy: 'recent',
showActiveOnly: false,
hideDefaultBranchWorkspace: false,

View File

@ -1715,7 +1715,6 @@ export type PersistedUIState = {
sidebarWidth: number
rightSidebarWidth: number
groupBy: 'none' | 'workspace-status' | 'repo' | 'pr-status'
showWorkspaceLineage?: boolean
sortBy: 'name' | 'smart' | 'recent' | 'repo'
showActiveOnly: boolean
/** Hide the repo's original checked-out branch from workspace navigation