diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx index 9d7605227f..f3ea62f1ed 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -78,6 +78,252 @@ export const FileExplorer = (props: FileExplorerProps) => { setState(workspaceState) }, [workspaceState]) + useEffect(() => { + if (treeRef.current) { + const keyPressHandler = (e: KeyboardEvent) => { + if (e.shiftKey) { + setState((prevState) => { + return { ...prevState, ctrlKey: true } + }) + } + } + + const keyUpHandler = (e: KeyboardEvent) => { + if (!e.shiftKey) { + setState((prevState) => { + return { ...prevState, ctrlKey: false } + }) + } + } + const targetDocument = treeRef.current + + targetDocument.addEventListener('keydown', keyPressHandler) + targetDocument.addEventListener('keyup', keyUpHandler) + return () => { + targetDocument.removeEventListener('keydown', keyPressHandler) + targetDocument.removeEventListener('keyup', keyUpHandler) + } + } + }, [treeRef.current]) + + useEffect(() => { + const performDeletion = async () => { + const path: string[] = [] + if (feTarget?.length > 0 && feTarget[0]?.key.length > 0) { + feTarget.forEach((one) => { + path.push(one.key) + }) + await deletePath(path) + } + } + + if (treeRef.current) { + const deleteKeyPressHandler = async (eve: KeyboardEvent) => { + if (eve.key === 'Delete' ) { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'deleteKey', 'deletePath']) + setState((prevState) => { + return { ...prevState, deleteKey: true } + }) + performDeletion() + return + } + if (eve.metaKey) { + if (eve.key === 'Backspace') { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'osxDeleteKey', 'deletePath']) + setState((prevState) => { + return { ...prevState, deleteKey: true } + }) + performDeletion() + return + } + } + } + const deleteKeyPressUpHandler = async (eve: KeyboardEvent) => { + if (eve.key === 'Delete' ) { + setState((prevState) => { + return { ...prevState, deleteKey: false } + }) + return + } + if (eve.metaKey) { + if (eve.key === 'Backspace') { + setState((prevState) => { + return { ...prevState, deleteKey: false } + }) + return + } + } + } + + treeRef.current?.addEventListener('keydown', deleteKeyPressHandler) + treeRef.current?.addEventListener('keyup', deleteKeyPressUpHandler) + return () => { + treeRef.current?.removeEventListener('keydown', deleteKeyPressHandler) + treeRef.current?.removeEventListener('keyup', deleteKeyPressUpHandler) + } + } + }, [treeRef.current, feTarget]) + + useEffect(() => { + const performRename = async () => { + if (feTarget?.length > 1 && feTarget[0]?.key.length > 1) { + await plugin.call('notification', 'alert', { id: 'renameAlert', message: 'You cannot rename multiple files at once!' }) + } + props.editModeOn(feTarget[0].key, feTarget[0].type, false) + } + if (treeRef.current) { + const F2KeyPressHandler = async (eve: KeyboardEvent) => { + if (eve.key === 'F2' ) { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'f2ToRename', 'RenamePath']) + await performRename() + setState((prevState) => { + return { ...prevState, F2Key: true } + }) + return + } + } + const F2KeyPressUpHandler = async (eve: KeyboardEvent) => { + if (eve.key === 'F2' ) { + setState((prevState) => { + return { ...prevState, F2Key: false } + }) + return + } + } + + treeRef.current?.addEventListener('keydown', F2KeyPressHandler) + treeRef.current?.addEventListener('keyup', F2KeyPressUpHandler) + return () => { + treeRef.current?.removeEventListener('keydown', F2KeyPressHandler) + treeRef.current?.removeEventListener('keyup', F2KeyPressUpHandler) + } + } + }, [treeRef.current, feTarget]) + + useEffect(() => { + const performCopy = async () => { + if (feTarget?.length > 0 && feTarget[0]?.key.length > 0) { + if (feTarget?.length > 1) { + handleMultiCopies(feTarget) + } else { + handleCopyClick(feTarget[0].key, feTarget[0].type) + } + } + } + + const performCut = async () => { + if (feTarget) { + if (feTarget.length > 0 && feTarget[0].key.length > 0) { + handleMultiCopies(feTarget) + setCutActivated(true) + } else { + handleCopyClick(feTarget[0].key, feTarget[0].type) + } + } + } + + const performPaste = async () => { + if (feTarget.length > 0 && feTarget[0]?.key.length >= 0) { + if (cutActivated) { + if (state.copyElement.length > 1) { + const promisesToKeep = state.copyElement.filter(x => x).map(async (item) => { + if (item.type === 'file') { + props.dispatchMoveFile(item.key, feTarget[0].key) + } else { + props.dispatchMoveFolder(item.key, feTarget[0].key) + } + }) + await Promise.all(promisesToKeep) + } else { + if (state.copyElement[0].type === 'file') { + props.dispatchMoveFile(state.copyElement[0].key, feTarget[0].key) + } else { + props.dispatchMoveFolder(state.copyElement[0].key, feTarget[0].key) + } + } + } else { + handlePasteClick(feTarget[0].key, feTarget[0].type) + } + } + } + + if (treeRef.current) { + const targetDocument = treeRef.current + let CopyComboHandler: (eve: KeyboardEvent) => Promise + let CutHandler: (eve: KeyboardEvent) => Promise + let pasteHandler: (eve: KeyboardEvent) => Promise + let pcCopyHandler: (eve: KeyboardEvent) => Promise + let pcCutHandler: (eve: KeyboardEvent) => Promise + let pcPasteHandler: (eve: KeyboardEvent) => Promise + + if ((window as any).navigator.userAgentData.platform === 'macOS') { + CopyComboHandler = async (eve: KeyboardEvent) => { + if (eve.metaKey && eve.code === 'KeyC') { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'f2ToRename', 'RenamePath']) + await performCopy() + return + } + } + + CutHandler = async (eve: KeyboardEvent) => { + if (eve.metaKey && eve.code === 'KeyX') { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'f2ToRename', 'RenamePath']) + await performCut() + return + } + } + + pasteHandler = async (eve: KeyboardEvent) => { + if (eve.metaKey && eve.code === 'KeyV') { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'metaVToPaste', 'PasteCopiedContent']) + performPaste() + return + } + } + } else { + pcCopyHandler = async (eve: KeyboardEvent) => { + if (eve.ctrlKey && (eve.key === 'c' || eve.key === 'C')) { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'f2ToRename', 'RenamePath']) + await performCopy() + return + } + } + + pcCutHandler = async (eve: KeyboardEvent) => { + if (eve.ctrlKey && eve.code === 'KeyX') { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'f2ToRename', 'RenamePath']) + await performCut() + return + } + } + + pcPasteHandler = async (eve: KeyboardEvent) => { + if (eve.key === 'Control' && eve.code === 'KeyV') { + feWindow._paq.push(['trackEvent', 'fileExplorer', 'ctrlVToPaste', 'PasteCopiedContent']) + performPaste() + return + } + } + } + + targetDocument?.addEventListener('keydown', CopyComboHandler) + targetDocument?.addEventListener('keydown', CutHandler) + targetDocument?.addEventListener('keydown', pasteHandler) + targetDocument?.addEventListener('keydown', pcPasteHandler) + targetDocument?.addEventListener('keydown', pcCopyHandler) + targetDocument?.addEventListener('keydown', pcCutHandler) + + return () => { + targetDocument?.removeEventListener('keydown', pasteHandler) + targetDocument?.removeEventListener('keydown', pcPasteHandler) + targetDocument?.removeEventListener('keydown', CutHandler) + targetDocument?.removeEventListener('keydown', pcCutHandler) + targetDocument?.removeEventListener('keydown', CopyComboHandler) + targetDocument?.removeEventListener('keydown', pcCopyHandler) + } + } + }, [treeRef.current, feTarget]) + const hasReservedKeyword = (content: string): boolean => { if (state.reservedKeywords.findIndex((value) => content.startsWith(value)) !== -1) return true else return false