Merge pull request #814 from ethereum/fix-FE

Fixed File-Explorer Bugs
pull/821/head
yann300 4 years ago committed by GitHub
commit 4e4b0de362
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 98
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx

@ -25,7 +25,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
focusPath: null, focusPath: null,
files: [], files: [],
fileManager: null, fileManager: null,
accessToken: null,
ctrlKey: false, ctrlKey: false,
newFileName: '', newFileName: '',
actions: [], actions: [],
@ -40,21 +39,22 @@ export const FileExplorer = (props: FileExplorerProps) => {
isNew: false, isNew: false,
lastEdit: '' lastEdit: ''
}, },
expandPath: [], expandPath: [name],
modalOptions: { focusModal: {
hide: true, hide: true,
title: '', title: '',
message: '', message: '',
ok: { ok: {
label: 'Ok', label: '',
fn: null fn: () => {}
}, },
cancel: { cancel: {
label: 'Cancel', label: '',
fn: null fn: () => {}
}, },
handleHide: null handleHide: null
}, },
modals: [],
toasterMsg: '' toasterMsg: ''
}) })
const editRef = useRef(null) const editRef = useRef(null)
@ -72,8 +72,6 @@ export const FileExplorer = (props: FileExplorerProps) => {
useEffect(() => { useEffect(() => {
(async () => { (async () => {
const fileManager = registry.get('filemanager').api const fileManager = registry.get('filemanager').api
const config = registry.get('config').api
const accessToken = config.get('settings/gist-access-token')
const files = await fetchDirectoryContent(name) const files = await fetchDirectoryContent(name)
const actions = [{ const actions = [{
id: 'newFile', id: 'newFile',
@ -120,7 +118,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
}] }]
setState(prevState => { setState(prevState => {
return { ...prevState, fileManager, accessToken, files, actions } return { ...prevState, fileManager, files, actions }
}) })
})() })()
}, []) }, [])
@ -196,6 +194,28 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
}, [externalUploads]) }, [externalUploads])
useEffect(() => {
if (state.modals.length > 0) {
setState(prevState => {
const focusModal = {
hide: false,
title: prevState.modals[0].title,
message: prevState.modals[0].message,
ok: prevState.modals[0].ok,
cancel: prevState.modals[0].cancel,
handleHide: prevState.modals[0].handleHide
}
prevState.modals.shift()
return {
...prevState,
focusModal,
modals: prevState.modals
}
})
}
}, [state.modals])
const resolveDirectory = async (folderPath, dir: File[], isChild = false): Promise<File[]> => { const resolveDirectory = async (folderPath, dir: File[], isChild = false): Promise<File[]> => {
if (!isChild && (state.focusEdit.element === 'browser/blank') && state.focusEdit.isNew && (dir.findIndex(({ path }) => path === 'browser/blank') === -1)) { if (!isChild && (state.focusEdit.element === 'browser/blank') && state.focusEdit.isNew && (dir.findIndex(({ path }) => path === 'browser/blank') === -1)) {
dir = state.focusEdit.type === 'file' ? [...dir, { dir = state.focusEdit.type === 'file' ? [...dir, {
@ -420,13 +440,14 @@ export const FileExplorer = (props: FileExplorerProps) => {
const fileExternallyChanged = (path: string, file: { content: string }) => { const fileExternallyChanged = (path: string, file: { content: string }) => {
const config = registry.get('config').api const config = registry.get('config').api
const editor = registry.get('editor').api
if (config.get('currentFile') === path && registry.editor.currentContent() && registry.editor.currentContent() !== file.content) { if (config.get('currentFile') === path && editor.currentContent() !== file.content) {
if (filesProvider.isReadOnly(path)) return registry.editor.setText(file.content) if (filesProvider.isReadOnly(path)) return editor.setText(file.content)
modal(path + ' changed', 'This file has been changed outside of Remix IDE.', { modal(path + ' changed', 'This file has been changed outside of Remix IDE.', {
label: 'Replace by the new content', label: 'Replace by the new content',
fn: () => { fn: () => {
registry.editor.setText(file.content) editor.setText(file.content)
} }
}, { }, {
label: 'Keep the content displayed in Remix', label: 'Keep the content displayed in Remix',
@ -482,11 +503,17 @@ export const FileExplorer = (props: FileExplorerProps) => {
const success = await filesProvider.set(name, event.target.result) const success = await filesProvider.set(name, event.target.result)
if (!success) { if (!success) {
modal('File Upload Failed', 'Failed to create file ' + name, { return modal('File Upload Failed', 'Failed to create file ' + name, {
label: 'Close', label: 'Close',
fn: async () => {} fn: async () => {}
}, null) }, null)
} }
const config = registry.get('config').api
const editor = registry.get('editor').api
if ((config.get('currentFile') === name) && (editor.currentContent() !== event.target.result)) {
editor.setText(event.target.result)
}
} }
fileReader.readAsText(file) fileReader.readAsText(file)
} }
@ -575,7 +602,10 @@ export const FileExplorer = (props: FileExplorerProps) => {
}, null) }, null)
} else { } else {
// check for token // check for token
if (!state.accessToken) { const config = registry.get('config').api
const accessToken = config.get('settings/gist-access-token')
if (!accessToken) {
modal('Authorize Token', 'Remix requires an access token (which includes gists creation permission). Please go to the settings tab to create one.', { modal('Authorize Token', 'Remix requires an access token (which includes gists creation permission). Please go to the settings tab to create one.', {
label: 'Close', label: 'Close',
fn: async () => {} fn: async () => {}
@ -583,7 +613,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
} else { } else {
const description = 'Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. \n Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=' + const description = 'Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. \n Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=' +
queryParams.get().version + '&optimize=' + queryParams.get().optimize + '&runs=' + queryParams.get().runs + '&gist=' queryParams.get().version + '&optimize=' + queryParams.get().optimize + '&runs=' + queryParams.get().runs + '&gist='
const gists = new Gists({ token: state.accessToken }) const gists = new Gists({ token: accessToken })
if (id) { if (id) {
const originalFileList = await getOriginalFiles(id) const originalFileList = await getOriginalFiles(id)
@ -645,7 +675,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
const handleHideModal = () => { const handleHideModal = () => {
setState(prevState => { setState(prevState => {
return { ...prevState, modalOptions: { ...state.modalOptions, hide: true } } return { ...prevState, focusModal: { ...state.focusModal, hide: true } }
}) })
} }
@ -653,15 +683,14 @@ export const FileExplorer = (props: FileExplorerProps) => {
setState(prevState => { setState(prevState => {
return { return {
...prevState, ...prevState,
modalOptions: { modals: [...prevState.modals,
...prevState.modalOptions, {
hide: false,
message, message,
title, title,
ok, ok,
cancel, cancel,
handleHide: handleHideModal handleHide: handleHideModal
} }]
} }
}) })
} }
@ -933,6 +962,20 @@ export const FileExplorer = (props: FileExplorerProps) => {
<TreeView id='treeView'> <TreeView id='treeView'>
<TreeViewItem id="treeViewItem" <TreeViewItem id="treeViewItem"
label={ label={
<div onClick={(e) => {
e.stopPropagation()
let expandPath = []
if (!state.expandPath.includes(props.name)) {
expandPath = [props.name, ...new Set([...state.expandPath])]
} else {
expandPath = [...new Set(state.expandPath.filter(key => key && (typeof key === 'string') && !key.startsWith(props.name)))]
}
setState(prevState => {
return { ...prevState, expandPath }
})
plugin.resetFocus(true)
}}>
<FileExplorerMenu <FileExplorerMenu
title={name} title={name}
menuItems={props.menuItems} menuItems={props.menuItems}
@ -942,8 +985,9 @@ export const FileExplorer = (props: FileExplorerProps) => {
uploadFile={uploadFile} uploadFile={uploadFile}
fileManager={state.fileManager} fileManager={state.fileManager}
/> />
</div>
} }
expand={true}> expand={state.expandPath.includes(props.name)}>
<div className='pb-2'> <div className='pb-2'>
<TreeView id='treeViewMenu'> <TreeView id='treeViewMenu'>
{ {
@ -958,11 +1002,11 @@ export const FileExplorer = (props: FileExplorerProps) => {
{ {
props.name && <ModalDialog props.name && <ModalDialog
id={ props.name } id={ props.name }
title={ state.modalOptions.title } title={ state.focusModal.title }
message={ state.modalOptions.message } message={ state.focusModal.message }
hide={ state.modalOptions.hide } hide={ state.focusModal.hide }
ok={ state.modalOptions.ok } ok={ state.focusModal.ok }
cancel={ state.modalOptions.cancel } cancel={ state.focusModal.cancel }
handleHide={ handleHideModal } handleHide={ handleHideModal }
/> />
} }

Loading…
Cancel
Save