export interface WorkbenchLayoutOptions { width: number contextOpen: boolean leftCollapsed: boolean rightCollapsed: boolean leftWidth: number rightWidth: number previewWidth: number rightTab: 'work' | 'files' filesView: 'list' | 'preview' previewOpen: boolean previewExpanded: boolean } export type WorkbenchPane = 'context' | 'conversation' | 'work' | 'files' const COMPACT_WORKBENCH_WIDTH = 1024 function boundedWidth(value: number, fallback: number, min: number, max: number) { return Math.min(max, Math.max(min, Number.isFinite(value) ? value : fallback)) } // Only the rendered widths are bounded. Saved desktop preferences stay in the store. export function selectWorkbenchLayout(options: WorkbenchLayoutOptions) { const width = Number.isFinite(options.width) ? Math.max(0, options.width) : 1440 const available = Math.max(0, width - 8) const compact = width < COMPACT_WORKBENCH_WIDTH const filesWide = options.rightTab === 'files' && options.filesView === 'preview' && options.previewOpen const previewExpanded = filesWide && options.previewExpanded && !options.rightCollapsed if (compact) { const pane: WorkbenchPane = options.contextOpen ? 'context' : options.rightCollapsed ? 'conversation' : options.rightTab return { compact, pane, showContext: pane === 'context', showConversation: pane === 'conversation', showRight: pane === 'work' || pane === 'files', contextCollapsed: false, previewExpanded, leftWidth: pane === 'context' ? available : 0, rightWidth: pane === 'work' || pane === 'files' ? available : 0, leftDivider: false, rightDivider: false, } } const showRight = !options.rightCollapsed const leftDivider = !options.leftCollapsed const rightDivider = showRight && !previewExpanded const panelCount = 1 + Number(!previewExpanded) + Number(showRight) const gutters = (panelCount - 1) * 4 + (Number(leftDivider) + Number(rightDivider)) * 8 const leftMin = options.leftCollapsed ? 52 : 220 const rightMin = showRight ? filesWide ? 420 : 280 : 0 let leftWidth = options.leftCollapsed ? 52 : boundedWidth(options.leftWidth, 260, leftMin, 420) let rightWidth = showRight ? filesWide ? boundedWidth(options.previewWidth, 700, rightMin, 1100) : boundedWidth(options.rightWidth, 360, rightMin, 560) : 0 if (previewExpanded) rightWidth = available - gutters - leftWidth else { const conversationMin = filesWide && showRight ? 320 : 360 const budget = available - gutters - conversationMin if (leftWidth + rightWidth > budget) { const extraLeft = leftWidth - leftMin const extraRight = rightWidth - rightMin const ratio = Math.max(0, budget - leftMin - rightMin) / (extraLeft + extraRight || 1) leftWidth = leftMin + Math.floor(extraLeft * ratio) rightWidth = rightMin + Math.floor(extraRight * ratio) } } const pane: WorkbenchPane = previewExpanded ? 'files' : 'conversation' return { compact, pane, showContext: true, showConversation: !previewExpanded, showRight, contextCollapsed: options.leftCollapsed, previewExpanded, leftWidth, rightWidth, leftDivider, rightDivider, } }