import React, { useEffect, useState } from 'react' import withErrorBoundary from '../../../infrastructure/error-boundary' import { useProjectContext } from '../../../shared/context/project-context' import { useFileTreeData } from '../../../shared/context/file-tree-data-context' import FileTreeContext from './file-tree-context' import FileTreeDraggablePreviewLayer from './file-tree-draggable-preview-layer' import FileTreeFolderList from './file-tree-folder-list' import FileTreeToolbar from './file-tree-toolbar' import FileTreeModalDelete from './modals/file-tree-modal-delete' import FileTreeModalCreateFolder from './modals/file-tree-modal-create-folder' import FileTreeModalError from './modals/file-tree-modal-error' import FileTreeContextMenu from './file-tree-context-menu' import FileTreeError from './file-tree-error' import { useDroppable } from '../contexts/file-tree-draggable' import { useFileTreeSocketListener } from '../hooks/file-tree-socket-listener' import FileTreeModalCreateFile from './modals/file-tree-modal-create-file' import FileTreeInner from './file-tree-inner' import { useDragLayer } from 'react-dnd' import classnames from 'classnames' import { pathInFolder } from '@/features/file-tree/util/path' const FileTreeRoot = React.memo<{ onSelect: () => void onDelete: () => void onInit: () => void isConnected: boolean setRefProviderEnabled: () => void setStartedFreeTrial: () => void reindexReferences: () => void refProviders: Record }>(function FileTreeRoot({ refProviders, reindexReferences, setRefProviderEnabled, setStartedFreeTrial, onSelect, onInit, onDelete, isConnected, }) { const [fileTreeContainer, setFileTreeContainer] = useState(null) const { _id: projectId } = useProjectContext() const { fileTreeData } = useFileTreeData() const isReady = Boolean(projectId && fileTreeData) useEffect(() => { if (fileTreeContainer) { const listener = (event: DragEvent) => { if (event.dataTransfer) { // store the dragged entity in dataTransfer const { dataset } = event.target as HTMLDivElement if ( dataset.fileId && dataset.fileType && dataset.fileType !== 'folder' ) { event.dataTransfer.setData( 'application/x-overleaf-file-id', dataset.fileId ) const filePath = pathInFolder(fileTreeData, dataset.fileId) if (filePath) { event.dataTransfer.setData( 'application/x-overleaf-file-path', filePath ) } } } } fileTreeContainer.addEventListener('dragstart', listener) return () => { fileTreeContainer.removeEventListener('dragstart', listener) } } }, [fileTreeContainer, fileTreeData]) useEffect(() => { if (isReady) onInit() }, [isReady, onInit]) if (!isReady) return null return (
{fileTreeContainer && ( {isConnected ? null :
} )}
) }) function FileTreeRootFolder({ onDelete }: { onDelete: () => void }) { useFileTreeSocketListener(onDelete) const { fileTreeData } = useFileTreeData() const { isOver, dropRef } = useDroppable(fileTreeData._id) const dragLayer = useDragLayer(monitor => ({ isDragging: monitor.isDragging(), item: monitor.getItem(), clientOffset: monitor.getClientOffset(), })) return ( <> ) } export default withErrorBoundary(FileTreeRoot, FileTreeError)