@ -23,7 +23,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
key : '' ,
type : 'folder'
} ] ,
focusPath : null ,
files : [ ] ,
fileManager : null ,
ctrlKey : false ,
@ -56,6 +55,13 @@ export const FileExplorer = (props: FileExplorerProps) => {
path : [ ] ,
extension : [ ] ,
pattern : [ ]
} , {
id : 'run' ,
name : 'Run' ,
type : [ ] ,
path : [ ] ,
extension : [ '.js' ] ,
pattern : [ ]
} , {
id : 'pushChangesToGist' ,
name : 'Push changes to gist' ,
@ -78,11 +84,11 @@ export const FileExplorer = (props: FileExplorerProps) => {
extension : [ ] ,
pattern : [ ]
} , {
id : 'run ' ,
name : 'Run ' ,
type : [ ] ,
id : 'copy ' ,
name : 'Copy ' ,
type : [ 'folder' , 'file' ] ,
path : [ ] ,
extension : [ '.js' ] ,
extension : [ ] ,
pattern : [ ]
} ] ,
focusContext : {
@ -112,8 +118,10 @@ export const FileExplorer = (props: FileExplorerProps) => {
toasterMsg : '' ,
mouseOverElement : null ,
showContextMenu : false ,
reservedKeywords : [ name , 'gist-' ]
reservedKeywords : [ name , 'gist-' ] ,
copyElement : [ ]
} )
const [ canPaste , setCanPaste ] = useState ( false )
const [ fileSystem , dispatch ] = useReducer ( fileSystemReducer , fileSystemInitialState )
const editRef = useRef ( null )
@ -176,12 +184,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
useEffect ( ( ) = > {
if ( contextMenuItems ) {
setState ( prevState = > {
// filter duplicate items
const items = contextMenuItems . filter ( ( { name } ) = > prevState . actions . findIndex ( action = > action . name === name ) === - 1 )
return { . . . prevState , actions : [ . . . prevState . actions , . . . items ] }
} )
addMenuItems ( contextMenuItems )
}
} , [ contextMenuItems ] )
@ -223,6 +226,38 @@ export const FileExplorer = (props: FileExplorerProps) => {
}
} , [ state . modals ] )
useEffect ( ( ) = > {
if ( canPaste ) {
addMenuItems ( [ {
id : 'paste' ,
name : 'Paste' ,
type : [ 'folder' , 'file' ] ,
path : [ ] ,
extension : [ ] ,
pattern : [ ]
} ] )
} else {
removeMenuItems ( [ 'paste' ] )
}
} , [ canPaste ] )
const addMenuItems = ( items : { id : string , name : string , type : string [ ] , path : string [ ] , extension : string [ ] , pattern : string [ ] } [ ] ) = > {
setState ( prevState = > {
// filter duplicate items
const actions = items . filter ( ( { name } ) = > prevState . actions . findIndex ( action = > action . name === name ) === - 1 )
return { . . . prevState , actions : [ . . . prevState . actions , . . . actions ] }
} )
}
const removeMenuItems = ( ids : string [ ] ) = > {
setState ( prevState = > {
const actions = prevState . actions . filter ( ( { id } ) = > ids . findIndex ( value = > value === id ) === - 1 )
return { . . . prevState , actions }
} )
}
const extractNameFromKey = ( key : string ) : string = > {
const keyPath = key . split ( '/' )
@ -378,6 +413,26 @@ export const FileExplorer = (props: FileExplorerProps) => {
} )
}
const copyFile = ( src : string , dest : string ) = > {
const fileManager = state . fileManager
try {
fileManager . copyFile ( src , dest )
} catch ( error ) {
console . log ( 'Oops! An error ocurred while performing copyFile operation.' + error )
}
}
const copyFolder = ( src : string , dest : string ) = > {
const fileManager = state . fileManager
try {
fileManager . copyDir ( src , dest )
} catch ( error ) {
console . log ( 'Oops! An error ocurred while performing copyDir operation.' + error )
}
}
const publishToGist = ( path? : string , type ? : string ) = > {
modal ( 'Create a public gist' , ` Are you sure you want to anonymously publish all your files in the ${ name } workspace as a public gist on github.com? ` , 'OK' , ( ) = > toGist ( path , type ) , 'Cancel' , ( ) = > { } )
}
@ -695,6 +750,25 @@ export const FileExplorer = (props: FileExplorerProps) => {
} )
}
const handleCopyClick = ( path : string , type : string ) = > {
setState ( prevState = > {
return { . . . prevState , copyElement : [ { key : path , type } ] }
} )
setCanPaste ( true )
toast ( ` Copied to clipboard ${ path } ` )
}
const handlePasteClick = ( dest : string , destType : string ) = > {
dest = destType === 'file' ? extractParentFromKey ( dest ) || props.name : dest
state . copyElement . map ( ( { key , type } ) = > {
type === 'file' ? copyFile ( key , dest ) : copyFolder ( key , dest )
} )
setState ( prevState = > {
return { . . . prevState , copyElement : [ ] }
} )
setCanPaste ( false )
}
const label = ( file : File ) = > {
return (
< div
@ -868,6 +942,8 @@ export const FileExplorer = (props: FileExplorerProps) => {
deletePath = { deletePath }
renamePath = { editModeOn }
runScript = { runScript }
copy = { handleCopyClick }
paste = { handlePasteClick }
emit = { emitContextMenuEvent }
pageX = { state . focusContext . x }
pageY = { state . focusContext . y }