|
|
|
@ -1,28 +1,34 @@ |
|
|
|
|
// eslint-disable-next-line no-use-before-define
|
|
|
|
|
import React, { SyntheticEvent, useEffect, useState } from 'react' |
|
|
|
|
import { FileType } from '../types' |
|
|
|
|
import React, {SyntheticEvent, useEffect, useState} from 'react' |
|
|
|
|
import {FileType} from '../types' |
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
|
import { TreeView, TreeViewItem } from '@remix-ui/tree-view' |
|
|
|
|
import { getPathIcon } from '@remix-ui/helper' |
|
|
|
|
import {TreeView, TreeViewItem} from '@remix-ui/tree-view' |
|
|
|
|
import {getPathIcon} from '@remix-ui/helper' |
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
|
import { FileLabel } from './file-label' |
|
|
|
|
import { fileDecoration, FileDecorationIcons } from '@remix-ui/file-decorators' |
|
|
|
|
import { Draggable } from "@remix-ui/drag-n-drop" |
|
|
|
|
import {FileLabel} from './file-label' |
|
|
|
|
import {fileDecoration, FileDecorationIcons} from '@remix-ui/file-decorators' |
|
|
|
|
import {Draggable} from '@remix-ui/drag-n-drop' |
|
|
|
|
|
|
|
|
|
export interface RenderFileProps { |
|
|
|
|
file: FileType, |
|
|
|
|
index: number, |
|
|
|
|
focusEdit: { element: string, type: string, isNew: boolean, lastEdit: string }, |
|
|
|
|
focusElement: { key: string, type: 'file' | 'folder' | 'gist' }[], |
|
|
|
|
focusContext: { element: string, x: number, y: number, type: string }, |
|
|
|
|
ctrlKey: boolean, |
|
|
|
|
expandPath: string[], |
|
|
|
|
hideIconsMenu?: React.Dispatch<React.SetStateAction<boolean>>, |
|
|
|
|
showIconsMenu?: boolean, |
|
|
|
|
editModeOff: (content: string) => void, |
|
|
|
|
handleClickFolder: (path: string, type: string) => void, |
|
|
|
|
handleClickFile: (path: string, type: string) => void, |
|
|
|
|
handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void |
|
|
|
|
file: FileType |
|
|
|
|
index: number |
|
|
|
|
focusEdit: {element: string; type: string; isNew: boolean; lastEdit: string} |
|
|
|
|
focusElement: {key: string; type: 'file' | 'folder' | 'gist'}[] |
|
|
|
|
focusContext: {element: string; x: number; y: number; type: string} |
|
|
|
|
ctrlKey: boolean |
|
|
|
|
expandPath: string[] |
|
|
|
|
hideIconsMenu?: React.Dispatch<React.SetStateAction<boolean>> |
|
|
|
|
showIconsMenu?: boolean |
|
|
|
|
editModeOff: (content: string) => void |
|
|
|
|
handleClickFolder: (path: string, type: string) => void |
|
|
|
|
handleClickFile: (path: string, type: string) => void |
|
|
|
|
handleContextMenu: ( |
|
|
|
|
pageX: number, |
|
|
|
|
pageY: number, |
|
|
|
|
path: string, |
|
|
|
|
content: string, |
|
|
|
|
type: string |
|
|
|
|
) => void |
|
|
|
|
fileDecorations: fileDecoration[] |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -38,11 +44,17 @@ export const FileRender = (props: RenderFileProps) => { |
|
|
|
|
} |
|
|
|
|
}, [props.file]) |
|
|
|
|
|
|
|
|
|
const labelClass = props.focusEdit.element === file.path |
|
|
|
|
? 'bg-light' : props.focusElement.findIndex(item => item.key === file.path) !== -1 |
|
|
|
|
? 'bg-secondary' : hover |
|
|
|
|
? 'bg-light border-no-shift' : (props.focusContext.element === file.path) && (props.focusEdit.element !== file.path) |
|
|
|
|
? 'bg-light border-no-shift' : '' |
|
|
|
|
const labelClass = |
|
|
|
|
props.focusEdit.element === file.path |
|
|
|
|
? 'bg-light' |
|
|
|
|
: props.focusElement.findIndex((item) => item.key === file.path) !== -1 |
|
|
|
|
? 'bg-secondary' |
|
|
|
|
: hover |
|
|
|
|
? 'bg-light border-no-shift' |
|
|
|
|
: props.focusContext.element === file.path && |
|
|
|
|
props.focusEdit.element !== file.path |
|
|
|
|
? 'bg-light border-no-shift' |
|
|
|
|
: '' |
|
|
|
|
|
|
|
|
|
const spreadProps = { |
|
|
|
|
onClick: (e) => e.stopPropagation() |
|
|
|
@ -50,20 +62,28 @@ export const FileRender = (props: RenderFileProps) => { |
|
|
|
|
|
|
|
|
|
const handleFolderClick = (event: SyntheticEvent) => { |
|
|
|
|
event.stopPropagation() |
|
|
|
|
if (props.focusEdit.element !== file.path) props.handleClickFolder(file.path, file.type) |
|
|
|
|
if (props.focusEdit.element !== file.path) |
|
|
|
|
props.handleClickFolder(file.path, file.type) |
|
|
|
|
if (props.showIconsMenu === true) props.hideIconsMenu(!props.showIconsMenu) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const handleFileClick = (event: SyntheticEvent) => { |
|
|
|
|
event.stopPropagation() |
|
|
|
|
if (props.focusEdit.element !== file.path) props.handleClickFile(file.path, file.type) |
|
|
|
|
if (props.focusEdit.element !== file.path) |
|
|
|
|
props.handleClickFile(file.path, file.type) |
|
|
|
|
if (props.showIconsMenu === true) props.hideIconsMenu(!props.showIconsMenu) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const handleContextMenu = (event: PointerEvent) => { |
|
|
|
|
event.preventDefault() |
|
|
|
|
event.stopPropagation() |
|
|
|
|
props.handleContextMenu(event.pageX, event.pageY, file.path, (event.target as HTMLElement).textContent, file.type) |
|
|
|
|
props.handleContextMenu( |
|
|
|
|
event.pageX, |
|
|
|
|
event.pageY, |
|
|
|
|
file.path, |
|
|
|
|
(event.target as HTMLElement).textContent, |
|
|
|
|
file.type |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const handleMouseOut = (event: SyntheticEvent) => { |
|
|
|
@ -80,17 +100,36 @@ export const FileRender = (props: RenderFileProps) => { |
|
|
|
|
return ( |
|
|
|
|
<TreeViewItem |
|
|
|
|
id={`treeViewItem${file.path}`} |
|
|
|
|
iconX='pr-3 fa fa-folder' |
|
|
|
|
iconY='pr-3 fa fa-folder-open' |
|
|
|
|
iconX="pr-3 fa fa-folder" |
|
|
|
|
iconY={ |
|
|
|
|
props.expandPath.includes(file.path) |
|
|
|
|
? 'pr-0 fa fa-folder-open' |
|
|
|
|
: 'pr-3 fa fa-folder' |
|
|
|
|
} |
|
|
|
|
key={`${file.path + props.index}`} |
|
|
|
|
label={<> |
|
|
|
|
<Draggable isDraggable={props.focusEdit.element !== null} file={file} expandedPath={props.expandPath} handleClickFolder={props.handleClickFolder}> |
|
|
|
|
<div className="d-flex flex-row"> |
|
|
|
|
<FileLabel fileDecorations={props.fileDecorations} file={file} focusEdit={props.focusEdit} editModeOff={props.editModeOff} /> |
|
|
|
|
<FileDecorationIcons file={file} fileDecorations={props.fileDecorations} /> |
|
|
|
|
</div> |
|
|
|
|
</Draggable> |
|
|
|
|
</>} |
|
|
|
|
label={ |
|
|
|
|
<> |
|
|
|
|
<Draggable |
|
|
|
|
isDraggable={props.focusEdit.element !== null} |
|
|
|
|
file={file} |
|
|
|
|
expandedPath={props.expandPath} |
|
|
|
|
handleClickFolder={props.handleClickFolder} |
|
|
|
|
> |
|
|
|
|
<div className="d-flex flex-row"> |
|
|
|
|
<FileLabel |
|
|
|
|
fileDecorations={props.fileDecorations} |
|
|
|
|
file={file} |
|
|
|
|
focusEdit={props.focusEdit} |
|
|
|
|
editModeOff={props.editModeOff} |
|
|
|
|
/> |
|
|
|
|
<FileDecorationIcons |
|
|
|
|
file={file} |
|
|
|
|
fileDecorations={props.fileDecorations} |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</Draggable> |
|
|
|
|
</> |
|
|
|
|
} |
|
|
|
|
onClick={handleFolderClick} |
|
|
|
|
onContextMenu={handleContextMenu} |
|
|
|
|
labelClass={labelClass} |
|
|
|
@ -99,26 +138,37 @@ export const FileRender = (props: RenderFileProps) => { |
|
|
|
|
onMouseOver={handleMouseOver} |
|
|
|
|
onMouseOut={handleMouseOut} |
|
|
|
|
> |
|
|
|
|
{ |
|
|
|
|
file.child ? <TreeView id={`treeView${file.path}`} key={`treeView${file.path}`} {...spreadProps}>{ |
|
|
|
|
Object.keys(file.child).map((key, index) => <FileRender |
|
|
|
|
file={file.child[key]} |
|
|
|
|
fileDecorations={props.fileDecorations} |
|
|
|
|
index={index} |
|
|
|
|
focusContext={props.focusContext} |
|
|
|
|
focusEdit={props.focusEdit} |
|
|
|
|
focusElement={props.focusElement} |
|
|
|
|
ctrlKey={props.ctrlKey} |
|
|
|
|
editModeOff={props.editModeOff} |
|
|
|
|
handleClickFile={props.handleClickFile} |
|
|
|
|
handleClickFolder={props.handleClickFolder} |
|
|
|
|
handleContextMenu={props.handleContextMenu} |
|
|
|
|
expandPath={props.expandPath} |
|
|
|
|
key={index} |
|
|
|
|
/>) |
|
|
|
|
} |
|
|
|
|
</TreeView> : <TreeView id={`treeView${file.path}`} key={`treeView${file.path}`} {...spreadProps} /> |
|
|
|
|
} |
|
|
|
|
{file.child ? ( |
|
|
|
|
<TreeView |
|
|
|
|
id={`treeView${file.path}`} |
|
|
|
|
key={`treeView${file.path}`} |
|
|
|
|
{...spreadProps} |
|
|
|
|
> |
|
|
|
|
{Object.keys(file.child).map((key, index) => ( |
|
|
|
|
<FileRender |
|
|
|
|
file={file.child[key]} |
|
|
|
|
fileDecorations={props.fileDecorations} |
|
|
|
|
index={index} |
|
|
|
|
focusContext={props.focusContext} |
|
|
|
|
focusEdit={props.focusEdit} |
|
|
|
|
focusElement={props.focusElement} |
|
|
|
|
ctrlKey={props.ctrlKey} |
|
|
|
|
editModeOff={props.editModeOff} |
|
|
|
|
handleClickFile={props.handleClickFile} |
|
|
|
|
handleClickFolder={props.handleClickFolder} |
|
|
|
|
handleContextMenu={props.handleContextMenu} |
|
|
|
|
expandPath={props.expandPath} |
|
|
|
|
key={index} |
|
|
|
|
/> |
|
|
|
|
))} |
|
|
|
|
</TreeView> |
|
|
|
|
) : ( |
|
|
|
|
<TreeView |
|
|
|
|
id={`treeView${file.path}`} |
|
|
|
|
key={`treeView${file.path}`} |
|
|
|
|
{...spreadProps} |
|
|
|
|
/> |
|
|
|
|
)} |
|
|
|
|
</TreeViewItem> |
|
|
|
|
) |
|
|
|
|
} else { |
|
|
|
@ -128,10 +178,23 @@ export const FileRender = (props: RenderFileProps) => { |
|
|
|
|
key={`treeView${file.path}`} |
|
|
|
|
label={ |
|
|
|
|
<> |
|
|
|
|
<Draggable isDraggable={props.focusEdit.element !== null} file={file} expandedPath={props.expandPath} handleClickFolder={props.handleClickFolder}> |
|
|
|
|
<Draggable |
|
|
|
|
isDraggable={props.focusEdit.element !== null} |
|
|
|
|
file={file} |
|
|
|
|
expandedPath={props.expandPath} |
|
|
|
|
handleClickFolder={props.handleClickFolder} |
|
|
|
|
> |
|
|
|
|
<div className="d-flex flex-row"> |
|
|
|
|
<FileLabel fileDecorations={props.fileDecorations} file={file} focusEdit={props.focusEdit} editModeOff={props.editModeOff} /> |
|
|
|
|
<FileDecorationIcons file={file} fileDecorations={props.fileDecorations} /> |
|
|
|
|
<FileLabel |
|
|
|
|
fileDecorations={props.fileDecorations} |
|
|
|
|
file={file} |
|
|
|
|
focusEdit={props.focusEdit} |
|
|
|
|
editModeOff={props.editModeOff} |
|
|
|
|
/> |
|
|
|
|
<FileDecorationIcons |
|
|
|
|
file={file} |
|
|
|
|
fileDecorations={props.fileDecorations} |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
</Draggable> |
|
|
|
|
</> |
|
|
|
|