fix: pin workbar tab order and preserve browser titles

This commit is contained in:
mesalogo
2026-09-10 08:46:17 +08:00
parent c1848a9dc4
commit fedafa21bd
13 changed files with 209 additions and 41 deletions
+36 -4
View File
@@ -25,8 +25,8 @@ describe('workbar contracts', () => {
reorderable
}))
).toEqual([
{ id: 'tasks', instancePolicy: 'single', defaultContext: 'current-project', defaultOpen: true, required: true, closable: false, reorderable: true },
{ id: 'workspace', instancePolicy: 'single', defaultContext: 'current-project', defaultOpen: true, required: true, closable: false, reorderable: true },
{ id: 'tasks', instancePolicy: 'single', defaultContext: 'current-project', defaultOpen: true, required: true, closable: false, reorderable: false },
{ id: 'workspace', instancePolicy: 'single', defaultContext: 'current-project', defaultOpen: true, required: true, closable: false, reorderable: false },
{ id: 'browser', instancePolicy: 'multiple', defaultContext: 'current-conversation', defaultOpen: true, required: false, closable: true, reorderable: true },
{ id: 'results', instancePolicy: 'single', defaultContext: 'current-project', defaultOpen: true, required: false, closable: true, reorderable: true },
{
@@ -209,14 +209,46 @@ describe('workbar contracts', () => {
expect(normalized?.instances.map(({ id, appId }) => ({ id, appId })))
.toEqual([
{ id: taskId, appId: 'tasks' },
{ id: workspaceId, appId: 'workspace' },
{ id: browserId, appId: 'browser' },
{ id: secondBrowserId, appId: 'browser' },
{ id: workspaceId, appId: 'workspace' }
{ id: secondBrowserId, appId: 'browser' }
])
expect(normalized?.activeInstanceId).toBe(taskId)
expect(normalized?.taskScope).toBe('all-projects')
})
it('pins restored tasks and workspace without changing other order or selection', () => {
const workspace = {
id: '00000000-0000-4000-8000-000000000105',
appId: 'workspace', title: 'Workspace'
} as const
const tasks = { id: taskId, appId: 'tasks', title: 'Tasks' } as const
const terminal = {
id: terminalId, appId: 'terminal', title: 'Terminal',
targetRef: { type: 'local' }
} as const
const browser = {
id: '00000000-0000-4000-8000-000000000103',
appId: 'browser', title: 'Browser',
targetRef: { type: 'conversation', conversationId: 'conversation-a' }
} as const
const layout = {
instances: [terminal, workspace, browser, tasks],
activeInstanceId: browser.id,
expanded: true, dock: 'right', widthRatio: 0.4,
taskScope: 'all-projects'
} as const
const normalized = normalizeWorkbarLayoutPreferences(layout, [tasks, workspace])
expect(normalized).toEqual({
...layout,
instances: [tasks, workspace, terminal, browser]
})
expect(layout.instances).toEqual([terminal, workspace, browser, tasks])
expect(normalizeWorkbarLayoutPreferences(normalized, [tasks, workspace]))
.toEqual(normalized)
})
it('preserves a valid empty layout with a null active instance', () => {
expect(
normalizeWorkbarLayoutPreferences(
+15 -3
View File
@@ -107,7 +107,7 @@ export const WORKBAR_APP_DEFINITIONS = [
defaultOpen: true,
required: true,
closable: false,
reorderable: true,
reorderable: false,
availability: { state: 'available' }
},
{
@@ -121,7 +121,7 @@ export const WORKBAR_APP_DEFINITIONS = [
defaultOpen: true,
required: true,
closable: false,
reorderable: true,
reorderable: false,
availability: { state: 'available' }
},
{
@@ -317,6 +317,18 @@ export type WorkbarLayoutPreferences = z.infer<
typeof workbarLayoutPreferencesSchema
>
export function orderWorkbarInstances(
instances: readonly WorkbarTabInstance[]
): WorkbarTabInstance[] {
return [
...instances.filter((instance) => instance.appId === 'tasks'),
...instances.filter((instance) => instance.appId === 'workspace'),
...instances.filter(
(instance) => instance.appId !== 'tasks' && instance.appId !== 'workspace'
)
]
}
export function normalizeWorkbarLayoutPreferences(
value: unknown,
defaultInstances: readonly WorkbarTabInstance[]
@@ -374,7 +386,7 @@ export function normalizeWorkbarLayoutPreferences(
)
}
const boundedInstances = instances.slice(
const boundedInstances = orderWorkbarInstances(instances).slice(
0,
WORKBAR_LIMITS.maximumOpenInstances
)