Files
kandev/apps/web/components/task/mobile/session-tablet-layout.tsx
T
2026-02-16 13:48:58 +00:00

152 lines
5.2 KiB
TypeScript

'use client';
import { memo, useMemo } from 'react';
import { Group, Panel } from 'react-resizable-panels';
import { SessionTaskSwitcherSheet } from './session-task-switcher-sheet';
import { TaskCenterPanel } from '../task-center-panel';
import { TaskRightPanel } from '../task-right-panel';
import { TaskFilesPanel } from '../task-files-panel';
import { PreviewPanel } from '@/components/task/preview/preview-panel';
import { PreviewController } from '@/components/task/preview/preview-controller';
import { useDefaultLayout } from '@/lib/layout/use-default-layout';
import { useLayoutStore } from '@/lib/state/layout-store';
import { useSessionLayoutState } from '@/hooks/use-session-layout-state';
import type { Repository } from '@/lib/types/http';
import type { Layout } from 'react-resizable-panels';
const DEFAULT_TABLET_LAYOUT: Record<string, number> = {
left: 60,
right: 40,
};
const DEFAULT_PREVIEW_LAYOUT: Record<string, number> = {
chat: 60,
preview: 40,
};
type SessionTabletLayoutProps = {
workspaceId: string | null;
workflowId: string | null;
sessionId?: string | null;
repository?: Repository | null;
defaultLayouts?: Record<string, Layout>;
};
export const SessionTabletLayout = memo(function SessionTabletLayout({
workspaceId,
workflowId,
sessionId = null,
repository = null,
defaultLayouts = {},
}: SessionTabletLayoutProps) {
// Use shared layout state hook
const {
effectiveSessionId,
sessionKey,
selectedDiff,
handleSelectDiff,
handleClearSelectedDiff,
openFileRequest,
handleOpenFile,
handleFileOpenHandled,
isTaskSwitcherOpen,
setMobileSessionTaskSwitcherOpen,
} = useSessionLayoutState({ sessionId });
const layoutBySession = useLayoutStore((state) => state.columnsBySessionId);
const layoutState = useMemo(
() => layoutBySession[sessionKey] ?? { left: true, chat: true, right: true, preview: false },
[layoutBySession, sessionKey]
);
const hasDevScript = Boolean(repository?.dev_script?.trim());
const sessionForPreview = effectiveSessionId;
const topFilesPanel = (
<TaskFilesPanel
onSelectDiff={handleSelectDiff}
onOpenFile={handleOpenFile}
/>
);
// Tablet layout: two columns (left for chat/plan/changes, right for files+terminal)
const tabletLayoutKey = 'task-layout-tablet-v1';
const { defaultLayout: tabletLayout, onLayoutChanged: onTabletLayoutChange } = useDefaultLayout({
id: tabletLayoutKey,
panelIds: ['left', 'right'],
baseLayout: DEFAULT_TABLET_LAYOUT,
serverDefaultLayout: defaultLayouts[tabletLayoutKey],
});
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 (
<div className="flex-1 min-h-0 px-2 pb-2">
<PreviewController sessionId={sessionForPreview} hasDevScript={hasDevScript} />
<Group
orientation="horizontal"
className="h-full min-h-0"
id={tabletLayoutKey}
key={tabletLayoutKey}
defaultLayout={tabletLayout}
onLayoutChanged={onTabletLayoutChange}
>
{/* Left Panel: Chat/Plan/Changes with tabs */}
<Panel id="left" minSize="300px" className="min-h-0 min-w-0">
{layoutState.preview ? (
<Group
orientation="horizontal"
className="h-full min-h-0 min-w-0"
id={previewLayoutKey}
key={previewLayoutKey}
defaultLayout={defaultPreviewLayout}
onLayoutChanged={onPreviewLayoutChange}
>
<Panel id="chat" minSize="300px" className="min-h-0 min-w-0">
<TaskCenterPanel
selectedDiff={selectedDiff}
openFileRequest={openFileRequest}
onDiffHandled={handleClearSelectedDiff}
onFileOpenHandled={handleFileOpenHandled}
/>
</Panel>
<Panel id="preview" minSize="300px" className="min-h-0 min-w-0">
<PreviewPanel sessionId={sessionForPreview} hasDevScript={hasDevScript} />
</Panel>
</Group>
) : (
<TaskCenterPanel
selectedDiff={selectedDiff}
openFileRequest={openFileRequest}
onDiffHandled={handleClearSelectedDiff}
onFileOpenHandled={handleFileOpenHandled}
sessionId={sessionId}
/>
)}
</Panel>
{/* Right Panel: Files + Terminal stacked */}
<Panel id="right" minSize="250px" className="min-h-0 min-w-0">
<TaskRightPanel topPanel={topFilesPanel} sessionId={sessionForPreview} repositoryId={repository?.id ?? null} />
</Panel>
</Group>
{/* Task Switcher Sheet - same as mobile */}
<SessionTaskSwitcherSheet
open={isTaskSwitcherOpen}
onOpenChange={setMobileSessionTaskSwitcherOpen}
workspaceId={workspaceId}
workflowId={workflowId}
/>
</div>
);
});