2022-05-11 07:26:47 -04:00
|
|
|
import { useEffect, useRef } from 'react'
|
2020-11-26 09:22:30 -05:00
|
|
|
import PropTypes from 'prop-types'
|
|
|
|
import classNames from 'classnames'
|
|
|
|
import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
import { useEditorContext } from '../../../../shared/context/editor-context'
|
2021-03-18 05:52:36 -04:00
|
|
|
import { useFileTreeMainContext } from '../../contexts/file-tree-main'
|
2020-11-26 09:22:30 -05:00
|
|
|
import { useDraggable } from '../../contexts/file-tree-draggable'
|
|
|
|
|
|
|
|
import FileTreeItemName from './file-tree-item-name'
|
|
|
|
import FileTreeItemMenu from './file-tree-item-menu'
|
2021-06-03 09:45:05 -04:00
|
|
|
import { useFileTreeSelectable } from '../../contexts/file-tree-selectable'
|
2020-11-26 09:22:30 -05:00
|
|
|
|
|
|
|
function FileTreeItemInner({ id, name, isSelected, icons }) {
|
2022-01-10 10:46:46 -05:00
|
|
|
const { permissionsLevel } = useEditorContext(editorContextPropTypes)
|
|
|
|
const { setContextMenuCoords } = useFileTreeMainContext()
|
2020-11-26 09:22:30 -05:00
|
|
|
|
2021-06-03 09:45:05 -04:00
|
|
|
const { selectedEntityIds } = useFileTreeSelectable()
|
|
|
|
|
|
|
|
const hasMenu =
|
2022-01-10 10:46:46 -05:00
|
|
|
permissionsLevel !== 'readOnly' &&
|
|
|
|
isSelected &&
|
|
|
|
selectedEntityIds.size === 1
|
2020-11-26 09:22:30 -05:00
|
|
|
|
2021-06-03 09:45:24 -04:00
|
|
|
const { isDragging, dragRef, setIsDraggable } = useDraggable(id)
|
2020-11-26 09:22:30 -05:00
|
|
|
|
2022-05-11 07:26:47 -04:00
|
|
|
const itemRef = useRef()
|
2020-11-26 09:22:30 -05:00
|
|
|
|
2020-12-15 05:23:54 -05:00
|
|
|
useEffect(() => {
|
2021-01-08 05:03:18 -05:00
|
|
|
const item = itemRef.current
|
|
|
|
if (isSelected && item) {
|
2021-01-12 06:24:27 -05:00
|
|
|
// we're delaying scrolling due to a race condition with other elements,
|
|
|
|
// mainly the Outline, being resized inside the same panel, causing the
|
|
|
|
// FileTree to have its viewport shrinked after the selected item is
|
|
|
|
// scrolled into the view, hiding it again.
|
|
|
|
// See `left-pane-resize-all` in `file-tree-controller` for more information.
|
2021-01-08 05:03:18 -05:00
|
|
|
setTimeout(() => {
|
|
|
|
if (item) {
|
|
|
|
scrollIntoViewIfNeeded(item, {
|
2021-04-27 03:52:58 -04:00
|
|
|
scrollMode: 'if-needed',
|
2021-01-08 05:03:18 -05:00
|
|
|
})
|
|
|
|
}
|
2021-01-12 06:24:27 -05:00
|
|
|
}, 100)
|
2020-12-15 05:23:54 -05:00
|
|
|
}
|
|
|
|
}, [isSelected, itemRef])
|
2020-11-26 09:22:30 -05:00
|
|
|
|
|
|
|
function handleContextMenu(ev) {
|
|
|
|
ev.preventDefault()
|
2021-11-09 06:01:08 -05:00
|
|
|
|
2020-11-26 09:22:30 -05:00
|
|
|
setContextMenuCoords({
|
|
|
|
top: ev.pageY,
|
2021-04-27 03:52:58 -04:00
|
|
|
left: ev.pageX,
|
2020-11-26 09:22:30 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={classNames('entity', {
|
2021-04-27 03:52:58 -04:00
|
|
|
'dnd-draggable-dragging': isDragging,
|
2020-11-26 09:22:30 -05:00
|
|
|
})}
|
|
|
|
role="presentation"
|
|
|
|
ref={dragRef}
|
|
|
|
onContextMenu={handleContextMenu}
|
|
|
|
>
|
|
|
|
<div
|
|
|
|
className="entity-name entity-name-react"
|
|
|
|
role="presentation"
|
|
|
|
ref={itemRef}
|
|
|
|
>
|
|
|
|
{icons}
|
2021-02-09 04:50:16 -05:00
|
|
|
<FileTreeItemName
|
|
|
|
name={name}
|
|
|
|
isSelected={isSelected}
|
|
|
|
setIsDraggable={setIsDraggable}
|
|
|
|
/>
|
2020-11-26 09:22:30 -05:00
|
|
|
{hasMenu ? <FileTreeItemMenu id={id} /> : null}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
FileTreeItemInner.propTypes = {
|
|
|
|
id: PropTypes.string.isRequired,
|
|
|
|
name: PropTypes.string.isRequired,
|
|
|
|
isSelected: PropTypes.bool.isRequired,
|
2021-04-27 03:52:58 -04:00
|
|
|
icons: PropTypes.node,
|
2020-11-26 09:22:30 -05:00
|
|
|
}
|
|
|
|
|
2022-01-10 10:46:46 -05:00
|
|
|
const editorContextPropTypes = {
|
|
|
|
permissionsLevel: PropTypes.oneOf(['readOnly', 'readAndWrite', 'owner']),
|
|
|
|
}
|
|
|
|
|
2020-11-26 09:22:30 -05:00
|
|
|
export default FileTreeItemInner
|