fix(desktop): closing main in a side-by-side layout promotes the neighboring session instead of spawning a fresh draft (#88924)
nextSessionTileForWorkspace() only walked tabs stacked WITH the workspace tab. In a side-by-side layout (session tiles in their own zones — db's three-pane report), the walk found nothing, closeWorkspaceTab() skipped promotion, and requestFreshSession() dropped main to a new draft: closing a pane read as 'it gave me a new session'. A tile in any zone now promotes (its zone collapses via the tile close), so Close is also the path from N panes back to 1. Ghost panes whose tile is gone still never promote.
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
blankDraftTile,
|
||||
focusedSessionNeedsRoute,
|
||||
markSelectionRestore,
|
||||
nextSessionTileForWorkspace,
|
||||
orderTilesByTree,
|
||||
releaseSessionTranscript,
|
||||
resetTileRuntimeBindings,
|
||||
@@ -111,6 +112,47 @@ describe('selectionHomesToWorkspace', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('nextSessionTileForWorkspace (⌘W promotion source)', () => {
|
||||
afterEach(() => {
|
||||
$layoutTree.set(null)
|
||||
$sessionTiles.set([])
|
||||
})
|
||||
|
||||
it('prefers a tile stacked WITH the workspace tab (nearest-out)', () => {
|
||||
$layoutTree.set(group(['workspace', tilePane('a'), tilePane('b')], { active: 'workspace', id: 'main' }))
|
||||
$sessionTiles.set([tile('a'), tile('b')])
|
||||
|
||||
expect(nextSessionTileForWorkspace()).toBe('a')
|
||||
})
|
||||
|
||||
it('side-by-side layout: a tile in ANOTHER zone still promotes instead of dropping main to a fresh draft (#88924)', () => {
|
||||
// main zone holds only the workspace; the session tile lives in its own
|
||||
// zone beside it — db's three-pane report shape.
|
||||
$layoutTree.set(
|
||||
split('row', [
|
||||
group(['workspace'], { active: 'workspace', id: 'main' }),
|
||||
group([tilePane('side')], { active: tilePane('side'), id: 'right' })
|
||||
])
|
||||
)
|
||||
$sessionTiles.set([tile('side')])
|
||||
|
||||
expect(nextSessionTileForWorkspace()).toBe('side')
|
||||
})
|
||||
|
||||
it('returns null when no live tile exists anywhere in the tree', () => {
|
||||
$layoutTree.set(
|
||||
split('row', [
|
||||
group(['workspace'], { active: 'workspace', id: 'main' }),
|
||||
group([tilePane('stale')], { active: tilePane('stale'), id: 'right' })
|
||||
])
|
||||
)
|
||||
// Pane persisted in the tree but its tile is gone — must not promote a ghost.
|
||||
$sessionTiles.set([])
|
||||
|
||||
expect(nextSessionTileForWorkspace()).toBe(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe('boot-restore selection homing (⌘R tab persistence)', () => {
|
||||
const mainGroup = () => group(['workspace', tilePane('t')], { active: tilePane('t'), id: 'main' })
|
||||
|
||||
|
||||
@@ -818,6 +818,17 @@ export function nextSessionTileForWorkspace(): null | string {
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing stacked WITH main — but a session tile in another zone can still
|
||||
// shift in. Without this, closing main in a side-by-side layout skipped
|
||||
// promotion entirely and dropped to a fresh "New session" draft, which read
|
||||
// as "closing a pane gave me a new session" (#88924). Promoting the tile
|
||||
// also collapses its zone, so Close is how a multi-pane layout shrinks.
|
||||
for (const tile of tiles) {
|
||||
if (tree && findGroupOfPane(tree, `${TILE_PANE_PREFIX}${tile.storedSessionId}`)) {
|
||||
return tile.storedSessionId
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user