'use client'; import { memo, useMemo, useState, useCallback } from 'react'; import { Group, Panel, type Layout } from 'react-resizable-panels'; import { useDefaultLayout } from '@/lib/layout/use-default-layout'; import { TaskCenterPanel } from './task-center-panel'; import { TaskRightPanel } from './task-right-panel'; import { TaskFilesPanel } from './task-files-panel'; import { TaskSessionSidebar } from './task-session-sidebar'; import { PreviewPanel } from '@/components/task/preview/preview-panel'; import { PreviewController } from '@/components/task/preview/preview-controller'; import { useLayoutStore } from '@/lib/state/layout-store'; import type { OpenFileTab } from '@/lib/types/backend'; import type { Repository } from '@/lib/types/http'; import { useAppStore } from '@/components/state-provider'; const DEFAULT_HORIZONTAL_LAYOUT: Record = { left: 18, chat: 57, preview: 57, right: 25, }; const DEFAULT_PREVIEW_LAYOUT: Record = { chat: 60, preview: 40, }; const DEFAULT_LAYOUT_STATE = { left: true, chat: true, right: true, preview: false }; type TaskLayoutProps = { workspaceId: string | null; boardId: string | null; sessionId?: string | null; repository?: Repository | null; defaultLayouts?: Record; }; export type SelectedDiff = { path: string; content?: string; // Optional: if provided, use this instead of looking up from git status }; export const TaskLayout = memo(function TaskLayout({ workspaceId, boardId, sessionId = null, repository = null, defaultLayouts = {}, }: TaskLayoutProps) { const [selectedDiff, setSelectedDiff] = useState(null); const [openFileRequest, setOpenFileRequest] = useState(null); const activeSessionId = useAppStore((state) => state.tasks.activeSessionId); const layoutBySession = useLayoutStore((state) => state.columnsBySessionId); const sessionKey = activeSessionId ?? sessionId ?? ''; const layoutState = useMemo( () => layoutBySession[sessionKey] ?? DEFAULT_LAYOUT_STATE, [layoutBySession, sessionKey] ); const hasDevScript = Boolean(repository?.dev_script?.trim()); const handleSelectDiff = useCallback((path: string, content?: string) => { setSelectedDiff({ path, content }); }, []); const handleOpenFile = useCallback((file: OpenFileTab) => { setOpenFileRequest(file); }, []); const handleDiffHandled = useCallback(() => { setSelectedDiff(null); }, []); const handleFileOpenHandled = useCallback(() => { setOpenFileRequest(null); }, []); const topFilesPanel = ( ); const sessionForPreview = activeSessionId ?? sessionId ?? null; const horizontalPanelIds = useMemo(() => { const ids: string[] = []; if (layoutState.left) ids.push('left'); ids.push(layoutState.preview ? 'preview' : 'chat'); if (layoutState.right) ids.push('right'); return ids; }, [layoutState.left, layoutState.preview, layoutState.right]); const horizontalLayoutKey = `task-layout-horizontal-v3:${horizontalPanelIds.join('|')}`; const { defaultLayout: defaultHorizontalLayout, onLayoutChanged: onHorizontalLayoutChange } = useDefaultLayout({ id: horizontalLayoutKey, panelIds: horizontalPanelIds, baseLayout: DEFAULT_HORIZONTAL_LAYOUT, serverDefaultLayout: defaultLayouts[horizontalLayoutKey], }); const previewPanelIds = ['chat', 'preview']; const previewLayoutKey = 'task-layout-preview-v2'; const { defaultLayout: defaultPreviewLayout, onLayoutChanged: onPreviewLayoutChange } = useDefaultLayout({ id: previewLayoutKey, panelIds: previewPanelIds, baseLayout: DEFAULT_PREVIEW_LAYOUT, serverDefaultLayout: defaultLayouts[previewLayoutKey], }); return (
{layoutState.left ? ( <> ) : null} {layoutState.preview ? ( ) : ( )} {layoutState.right ? ( <> ) : null}
); });