import { useCallback, useEffect, useRef, useState } from 'react'; import type { MouseEvent as ReactMouseEvent } from 'react'; import type { Project } from '../../../types/app'; import type { CodeEditorDiffInfo, CodeEditorFile } from '../types/types'; type UseEditorSidebarOptions = { selectedProject: Project | null; isMobile: boolean; initialWidth?: number; }; export const useEditorSidebar = ({ selectedProject, isMobile, initialWidth = 600, }: UseEditorSidebarOptions) => { const [editingFile, setEditingFile] = useState(null); const [editorWidth, setEditorWidth] = useState(initialWidth); const [editorExpanded, setEditorExpanded] = useState(false); const [isResizing, setIsResizing] = useState(false); const [hasManualWidth, setHasManualWidth] = useState(false); const resizeHandleRef = useRef(null); const handleFileOpen = useCallback( (filePath: string, diffInfo: CodeEditorDiffInfo | null = null) => { const normalizedPath = filePath.replace(/\\/g, '/'); const fileName = normalizedPath.split('/').pop() || filePath; setEditingFile({ name: fileName, path: filePath, // DB projectId is forwarded to the editor so it can read/save files // via `/api/projects/:projectId/file` endpoints. projectId: selectedProject?.projectId, diffInfo, }); }, [selectedProject?.projectId], ); const handleCloseEditor = useCallback(() => { setEditingFile(null); setEditorExpanded(false); }, []); const handleToggleEditorExpand = useCallback(() => { setEditorExpanded((previous) => !previous); }, []); const handleResizeStart = useCallback( (event: ReactMouseEvent) => { if (isMobile) { return; } // After first drag interaction, the editor width is user-controlled. setHasManualWidth(true); setIsResizing(true); event.preventDefault(); }, [isMobile], ); useEffect(() => { const handleMouseMove = (event: globalThis.MouseEvent) => { if (!isResizing) { return; } // Get the main container (parent of EditorSidebar's parent) that contains both left content and editor const editorContainer = resizeHandleRef.current?.parentElement; const mainContainer = editorContainer?.parentElement; if (!mainContainer) { return; } const containerRect = mainContainer.getBoundingClientRect(); // Calculate new editor width: distance from mouse to right edge of main container const newWidth = containerRect.right - event.clientX; const minWidth = 300; const maxWidth = containerRect.width * 0.8; if (newWidth >= minWidth && newWidth <= maxWidth) { setEditorWidth(newWidth); } }; const handleMouseUp = () => { setIsResizing(false); }; if (isResizing) { document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); document.body.style.cursor = 'col-resize'; document.body.style.userSelect = 'none'; } return () => { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); document.body.style.cursor = ''; document.body.style.userSelect = ''; }; }, [isResizing]); return { editingFile, editorWidth, editorExpanded, hasManualWidth, resizeHandleRef, handleFileOpen, handleCloseEditor, handleToggleEditorExpand, handleResizeStart, }; };