mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-27 13:31:28 +00:00
959fa06148
Remove duplicate className from Angular file tree GitOrigin-RevId: 238b1ad8631b5a861361113679a9f1f8a66da6ea
113 lines
3.7 KiB
TypeScript
113 lines
3.7 KiB
TypeScript
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'
|
|
|
|
const FileTreeRoot = React.memo<{
|
|
onSelect: () => void
|
|
onDelete: () => void
|
|
onInit: () => void
|
|
isConnected: boolean
|
|
setRefProviderEnabled: () => void
|
|
setStartedFreeTrial: () => void
|
|
reindexReferences: () => void
|
|
refProviders: Record<string, boolean>
|
|
}>(function FileTreeRoot({
|
|
refProviders,
|
|
reindexReferences,
|
|
setRefProviderEnabled,
|
|
setStartedFreeTrial,
|
|
onSelect,
|
|
onInit,
|
|
onDelete,
|
|
isConnected,
|
|
}) {
|
|
const [fileTreeContainer, setFileTreeContainer] =
|
|
useState<HTMLDivElement | null>(null)
|
|
const { _id: projectId } = useProjectContext()
|
|
const { fileTreeData } = useFileTreeData()
|
|
const isReady = Boolean(projectId && fileTreeData)
|
|
|
|
useEffect(() => {
|
|
if (isReady) onInit()
|
|
}, [isReady, onInit])
|
|
if (!isReady) return null
|
|
|
|
return (
|
|
<div
|
|
className="file-tree"
|
|
data-testid="file-tree"
|
|
ref={setFileTreeContainer}
|
|
>
|
|
{fileTreeContainer && (
|
|
<FileTreeContext
|
|
refProviders={refProviders}
|
|
setRefProviderEnabled={setRefProviderEnabled}
|
|
setStartedFreeTrial={setStartedFreeTrial}
|
|
reindexReferences={reindexReferences}
|
|
onSelect={onSelect}
|
|
fileTreeContainer={fileTreeContainer}
|
|
>
|
|
{isConnected ? null : <div className="disconnected-overlay" />}
|
|
<FileTreeToolbar />
|
|
<FileTreeContextMenu />
|
|
<FileTreeInner>
|
|
<FileTreeRootFolder onDelete={onDelete} />
|
|
</FileTreeInner>
|
|
<FileTreeModalDelete />
|
|
<FileTreeModalCreateFile />
|
|
<FileTreeModalCreateFolder />
|
|
<FileTreeModalError />
|
|
</FileTreeContext>
|
|
)}
|
|
</div>
|
|
)
|
|
})
|
|
|
|
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 (
|
|
<>
|
|
<FileTreeDraggablePreviewLayer isOver={isOver} {...dragLayer} />
|
|
<FileTreeFolderList
|
|
folders={fileTreeData.folders}
|
|
docs={fileTreeData.docs}
|
|
files={fileTreeData.fileRefs}
|
|
classes={{
|
|
root: classnames('file-tree-list', {
|
|
'file-tree-dragging': dragLayer.isDragging,
|
|
}),
|
|
}}
|
|
dropRef={dropRef as any}
|
|
dataTestId="file-tree-list-root"
|
|
/>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default withErrorBoundary(FileTreeRoot, FileTreeError)
|