fix(desktop): focus opened sessions and restore closed tab positions
This commit is contained in:
@@ -162,6 +162,8 @@ export function openSession(
|
||||
openSessionTile(storedSessionId, 'center')
|
||||
}
|
||||
|
||||
focusOpenSession(storedSessionId, workspaceScope)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ import {
|
||||
$sessionTiles,
|
||||
closeSessionTile,
|
||||
dropSessionState,
|
||||
focusOpenSession,
|
||||
holdSessionOwnerUntilForeground,
|
||||
openSessionTile,
|
||||
patchSessionTile,
|
||||
@@ -850,7 +851,7 @@ export function useSessionActions({
|
||||
setWorkspaceCwdOwner(stored)
|
||||
}
|
||||
|
||||
revealTreePane(`session-tile:${stored}`)
|
||||
focusOpenSession(stored, workspaceScope)
|
||||
|
||||
if (listed) {
|
||||
broadcastSessionsChanged()
|
||||
|
||||
@@ -1136,40 +1136,19 @@ describe('reopenLastClosedTile focuses the restored tab', () => {
|
||||
title: 'chat'
|
||||
})
|
||||
|
||||
// panes ← $sessionTiles (paneMirror stub). Adoption is synchronous on
|
||||
// register, so openSessionTile + focusOpenSession works the same tick.
|
||||
const registered = new Map<string, () => void>()
|
||||
|
||||
const syncTiles = () => {
|
||||
const wanted = new Set(states.$sessionTiles.get().map(t => t.storedSessionId))
|
||||
|
||||
for (const id of wanted) {
|
||||
if (registered.has(id)) {
|
||||
continue
|
||||
}
|
||||
|
||||
registered.set(
|
||||
id,
|
||||
registry.register({
|
||||
area: 'panes',
|
||||
data: { dock: { pane: 'workspace', pos: 'center' }, placement: 'main' },
|
||||
id: tilePane(id),
|
||||
render: () => null,
|
||||
title: id
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
for (const [id, dispose] of registered) {
|
||||
if (!wanted.has(id)) {
|
||||
dispose()
|
||||
registered.delete(id)
|
||||
tree.removeTreePane(tilePane(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
states.$sessionTiles.listen(syncTiles)
|
||||
const { paneMirror } = await import('@/app/chat/pane-mirror')
|
||||
paneMirror({
|
||||
source: states.$sessionTiles,
|
||||
key: tile => tile.storedSessionId,
|
||||
prefix: 'session-tile',
|
||||
dir: tile => tile.dir,
|
||||
anchor: tile => tile.anchor,
|
||||
before: tile => tile.before,
|
||||
minWidth: '10rem',
|
||||
title: id => id,
|
||||
render: () => null,
|
||||
close: states.closeSessionTile
|
||||
})()
|
||||
tree.watchContributedPanes()
|
||||
session.$selectedStoredSessionId.set('primary')
|
||||
tree.declareDefaultTree(model.group(['workspace'], { active: 'workspace', id: 'grp-main' }))
|
||||
@@ -1182,6 +1161,32 @@ describe('reopenLastClosedTile focuses the restored tab', () => {
|
||||
return { states, tree }
|
||||
}
|
||||
|
||||
it('restores the live strip slot after reordering and retains the exact owner', async () => {
|
||||
const { states, tree } = await setup()
|
||||
states.openSessionTile('after', 'center', 'workspace')
|
||||
tree.moveTreePane(tilePane('closed'), { groupId: 'grp-main', pos: 'center', before: 'workspace' })
|
||||
const order = findGroupOfPane(tree.$layoutTree.get()!, 'workspace')!.panes
|
||||
const ownerRoute = { connectionId: 'cloud', profile: 'agent' }
|
||||
states.patchSessionTile('closed', { ownerRoute })
|
||||
states.closeSessionTile('closed')
|
||||
tree.noteActiveTreeGroup(null)
|
||||
states.reopenLastClosedTile()
|
||||
expect(findGroupOfPane(tree.$layoutTree.get()!, 'workspace')!.panes).toEqual(order)
|
||||
expect(states.$focusedStoredSessionId.get()).toBe('closed')
|
||||
expect(states.sessionTileOwnerRoute('closed')).toEqual(ownerRoute)
|
||||
})
|
||||
|
||||
it('fronts a palette-opened tab from sidebar focus without replacing main', async () => {
|
||||
const { states, tree } = await setup()
|
||||
const { openSession } = await import('@/app/open-session')
|
||||
const navigate = vi.fn()
|
||||
tree.noteActiveTreeGroup('sidebar')
|
||||
openSession('palette-result', navigate, 'stack')
|
||||
expect(states.$focusedStoredSessionId.get()).toBe('palette-result')
|
||||
expect(findGroupOfPane(tree.$layoutTree.get()!, 'workspace')!.active).toBe(tilePane('palette-result'))
|
||||
expect(navigate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('fronts the restored tab after ⌘⇧T', async () => {
|
||||
const { states, tree } = await setup()
|
||||
|
||||
|
||||
@@ -1729,7 +1729,20 @@ export function closeSessionTile(storedSessionId: string) {
|
||||
const tile = $sessionTiles.get().find(t => t.storedSessionId === storedSessionId)
|
||||
|
||||
if (tile) {
|
||||
closedStack().push(toStored(tile))
|
||||
const tree = $layoutTree.get()
|
||||
const paneId = `${TILE_PANE_PREFIX}${storedSessionId}`
|
||||
const group = tree ? findGroupOfPane(tree, paneId) : null
|
||||
const siblings = group?.panes.filter(id => id !== paneId) ?? []
|
||||
closedStack().push({
|
||||
...toStored(tile),
|
||||
...(group && siblings.length
|
||||
? {
|
||||
anchor: siblings[0],
|
||||
before: group.panes[group.panes.indexOf(paneId) + 1] ?? null,
|
||||
dir: 'center'
|
||||
}
|
||||
: {})
|
||||
})
|
||||
}
|
||||
|
||||
saveTiles($sessionTiles.get().filter(t => t.storedSessionId !== storedSessionId))
|
||||
@@ -1905,7 +1918,9 @@ export function reopenLastClosedTile(): void {
|
||||
if (!$sessionTiles.get().some(t => t.storedSessionId === storedSessionId)) {
|
||||
openSessionTile(storedSessionId, tile.dir, tile.anchor, tile.before, {
|
||||
workspaceMode: tile.workspaceMode ?? 'sessions',
|
||||
workspaceOwnerKey: tile.workspaceOwnerKey
|
||||
workspaceOwnerKey: tile.workspaceOwnerKey,
|
||||
workspaceTabTitle: tile.workspaceTabTitle,
|
||||
ownerRoute: tile.ownerRoute
|
||||
})
|
||||
focusOpenSession(storedSessionId)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user