From a25a12ea3de07b1c5ffc230566b7d41e0d7b513f Mon Sep 17 00:00:00 2001 From: ioedeveloper Date: Mon, 14 Dec 2020 12:44:24 +0100 Subject: [PATCH] Add new file throughinput --- apps/remix-ide/src/app/files/remixd-handle.js | 2 +- apps/remix-ide/src/app/panels/file-panel.js | 49 +++-- .../src/lib/file-explorer-context-menu.tsx | 2 +- .../file-explorer/src/lib/file-explorer.tsx | 199 ++++++++++++------ .../file-explorer/src/lib/types/index.ts | 2 +- 5 files changed, 163 insertions(+), 91 deletions(-) diff --git a/apps/remix-ide/src/app/files/remixd-handle.js b/apps/remix-ide/src/app/files/remixd-handle.js index 311883e020..8d706441d7 100644 --- a/apps/remix-ide/src/app/files/remixd-handle.js +++ b/apps/remix-ide/src/app/files/remixd-handle.js @@ -83,7 +83,7 @@ export class RemixdHandle extends WebsocketPlugin { this.canceled() } }, 3000) - this.locahostProvider.init(_ => this.fileSystemExplorer.ensureRoot()) + this.locahostProvider.init() this.call('manager', 'activatePlugin', 'git') } } diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js index 1be971fb35..9617ed68af 100644 --- a/apps/remix-ide/src/app/panels/file-panel.js +++ b/apps/remix-ide/src/app/panels/file-panel.js @@ -54,29 +54,40 @@ module.exports = class Filepanel extends ViewPlugin { fileManager: this._components.registry.get('filemanager').api, config: this._components.registry.get('config').api } - this.el = yo` + this.hideRemixdExplorer = true + this.remixdExplorer = { + hide: () => { + this.hideRemixdExplorer = true + this.renderComponent() + }, + show: () => { + this.hideRemixdExplorer = false + this.renderComponent() + } + } + this.el = yo`
` - this.remixdHandle = new RemixdHandle({}, this._deps.fileProviders.localhost, appManager) + this.remixdHandle = new RemixdHandle(this.remixdExplorer, this._deps.fileProviders.localhost, appManager) this.event = new EventManager() // fileExplorer.ensureRoot() this._deps.fileProviders.localhost.event.register('connecting', (event) => { }) - this._deps.fileProviders.localhost.event.register('connected', (event) => { - fileSystemExplorer.show() - }) + // this._deps.fileProviders.localhost.event.register('connected', (event) => { + // fileSystemExplorer.show() + // }) - this._deps.fileProviders.localhost.event.register('errored', (event) => { - fileSystemExplorer.hide() - }) + // this._deps.fileProviders.localhost.event.register('errored', (event) => { + // fileSystemExplorer.hide() + // }) - this._deps.fileProviders.localhost.event.register('closed', (event) => { - fileSystemExplorer.hide() - }) + // this._deps.fileProviders.localhost.event.register('closed', (event) => { + // fileSystemExplorer.hide() + // }) this.renderComponent() } @@ -101,13 +112,15 @@ module.exports = class Filepanel extends ViewPlugin { />
- {/* */} + { !this.hideRemixdExplorer && + + }
diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx index c8d4c5fb5f..01fb51d6fe 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx @@ -38,7 +38,7 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => createNewFolder(path) break case 'Rename': - renamePath(path) + renamePath(path, type) break case 'Delete': deletePath(path) diff --git a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx index 866ae26547..55bec650c7 100644 --- a/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx +++ b/libs/remix-ui/file-explorer/src/lib/file-explorer.tsx @@ -29,8 +29,11 @@ export const FileExplorer = (props: FileExplorerProps) => { y: null }, focusEdit: { - element: null - } + element: null, + type: '', + isNew: false + }, + fileExternallyChanged: false }) useEffect(() => { @@ -94,7 +97,7 @@ export const FileExplorer = (props: FileExplorerProps) => { const files = [] const prefix = path.split('/')[0] - Object.keys(filesList).forEach(key => { + Object.keys(filesList || {}).forEach(key => { const path = prefix + '/' + key if (filesList[key].isDirectory) { @@ -129,15 +132,11 @@ export const FileExplorer = (props: FileExplorerProps) => { return keyPath.join('/') } - const createNewFile = (parentFolder?: string) => { - if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key : extractParentFromKey(state.focusElement[0].key) : name - // const self = this - // modalDialogCustom.prompt('Create new file', 'File Name (e.g Untitled.sol)', 'Untitled.sol', (input) => { - // if (!input) input = 'New file' + const createNewFile = (parentFolder: string, newFilePath: string) => { + // if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key : extractParentFromKey(state.focusElement[0].key) : name const fileManager = state.fileManager - const newFileName = parentFolder + '/' + 'unnamed' + Math.floor(Math.random() * 101) // get filename from state (state.newFileName) - helper.createNonClashingName(newFileName, filesProvider, async (error, newName) => { + helper.createNonClashingName(newFilePath, filesProvider, async (error, newName) => { // if (error) return tooltip('Failed to create file ' + newName + ' ' + error) if (error) return const createFile = await fileManager.writeFile(newName, '') @@ -145,7 +144,7 @@ export const FileExplorer = (props: FileExplorerProps) => { if (!createFile) { // tooltip('Failed to create file ' + newName) } else { - addFile(parentFolder, newFileName) + addFile(parentFolder, newFilePath) await fileManager.open(newName) } }) @@ -196,7 +195,6 @@ export const FileExplorer = (props: FileExplorerProps) => { return { ...prevState, files: updatedFiles } }) } catch (e) { - console.log('e: ', e) // tooltip(`Failed to remove file ${key}.`) } // }, @@ -212,7 +210,7 @@ export const FileExplorer = (props: FileExplorerProps) => { if (exists) return // modalDialogCustom.alert(File already exists.) await fileManager.rename(oldPath, newPath) - const files = await replacePath(oldPath, newPath, state.files) + const files = replacePath(oldPath, newPath, state.files) setState(prevState => { return { ...prevState, files } @@ -222,31 +220,60 @@ export const FileExplorer = (props: FileExplorerProps) => { } } - const addFile = async (parentFolder: string, newFileName: string) => { + const addFile = async (parentFolder: string, newFilePath: string) => { if (parentFolder === name) { setState(prevState => { return { ...prevState, files: [...prevState.files, { - path: newFileName, - name: extractNameFromKey(newFileName), + path: newFilePath, + name: extractNameFromKey(newFilePath), isDirectory: false }], - focusElement: [{ key: newFileName, type: 'file' }] + focusElement: [{ key: newFilePath, type: 'file' }] } }) } else { const updatedFiles = await resolveDirectory(parentFolder, state.files) setState(prevState => { - return { ...prevState, files: updatedFiles, focusElement: [{ key: newFileName, type: 'file' }] } + return { ...prevState, files: updatedFiles, focusElement: [{ key: newFilePath, type: 'file' }] } }) } - if (newFileName.includes('_test.sol')) { - plugin.events.trigger('newTestFileCreated', [newFileName]) + if (newFilePath.includes('_test.sol')) { + plugin.events.trigger('newTestFileCreated', [newFilePath]) } } + const addEmptyFile = (parentFolder: string, files: File[]): File[] => { + if (parentFolder === name) { + files.push({ + path: 'browser/blank', + name: '', + isDirectory: false + }) + return files + } + return files.map(file => { + if (file.child) { + if (file.path === parentFolder) { + file.child = [...file.child, { + path: file.path + '/blank', + name: '', + isDirectory: false + }] + return file + } else { + file.child = addEmptyFile(parentFolder, file.child) + + return file + } + } else { + return file + } + }) + } + const addFolder = async (parentFolder: string, newFolderName: string) => { if (parentFolder === name) { setState(prevState => { @@ -302,21 +329,6 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - // self._components = {} - // self._components.registry = localRegistry || globalRegistry - // self._deps = { - // config: self._components.registry.get('config').api, - // editor: self._components.registry.get('editor').api, - // fileManager: self._components.registry.get('filemanager').api - // } - - // self._components.registry.put({ api: self, name: `fileexplorer/${self.files.type}` }) - - // warn if file changed outside of Remix - // function remixdDialog () { - // return yo`
This file has been changed outside of Remix IDE.
` - // } - // props.files.event.register('fileExternallyChanged', (path, file) => { // if (self._deps.config.get('currentFile') === path && self._deps.editor.currentContent() && self._deps.editor.currentContent() !== file.content) { // if (this.files.isReadOnly(path)) return self._deps.editor.setText(file.content) @@ -367,20 +379,6 @@ export const FileExplorer = (props: FileExplorerProps) => { // } // } - const label = (data: File) => { - return ( -
- - { data.path.split('/').pop() } - -
- ) - } - const handleClickFile = (path: string) => { state.fileManager.open(path) setState(prevState => { @@ -426,32 +424,93 @@ export const FileExplorer = (props: FileExplorerProps) => { }) } - const editModeOn = (path: string) => { + const editModeOn = (path: string, type: string, isNew: boolean = false) => { if (filesProvider.isReadOnly(path)) return setState(prevState => { - return { ...prevState, focusEdit: { element: path } } + return { ...prevState, focusEdit: { element: path, isNew, type } } }) } - const editModeOff = (content: string) => { - if (!content) return - if (helper.checkSpecialChars(content)) { + const editModeOff = async (content: string) => { + const parentFolder = state.focusEdit.type === 'folder' ? state.focusEdit.element : extractParentFromKey(state.focusEdit.element) + + if (!content || (content.trim() === '')) { + if (state.focusEdit.isNew) { + const files = removePath(state.focusEdit.element, state.files) + const updatedFiles = files.filter(file => file) + + setState(prevState => { + return { ...prevState, files: updatedFiles, focusEdit: { element: null, isNew: false, type: '' } } + }) + } else { + // modalDialogCustom.alert('Are you sure you want to delete this file?') + if (true) { // eslint-disable-line + await deletePath(state.focusEdit.element) + + setState(prevState => { + return { ...prevState, focusEdit: { element: null, isNew: false, type: '' } } + }) + } else { + + } + } + return + } + if (state.focusEdit.isNew) { + createNewFile(parentFolder, parentFolder + '/' + content) + const files = removePath(state.focusEdit.element, state.files) + const updatedFiles = files.filter(file => file) + + setState(prevState => { + return { ...prevState, files: updatedFiles } + }) + } else { + if (helper.checkSpecialChars(content)) return // modalDialogCustom.alert('Special characters are not allowed') + const oldPath: string = state.focusEdit.element + const oldName = extractNameFromKey(oldPath) + const newPath = oldPath.replace(oldName, content) + + renamePath(oldPath, newPath) } - const oldPath = state.focusEdit.element - const oldName = extractNameFromKey(oldPath) - const newPath = oldPath.replace(oldName, content) + setState(prevState => { + return { ...prevState, focusEdit: { element: null, isNew: false, type: '' } } + }) + } + + const handleNewFileInput = (parentFolder?: string) => { + if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key : extractParentFromKey(state.focusElement[0].key) : name - renamePath(oldPath, newPath) + const files = addEmptyFile(parentFolder, state.files) setState(prevState => { - return { ...prevState, focusEdit: { element: null } } + return { ...prevState, files } }) + editModeOn(parentFolder + '/blank', 'file', true) + } + + // warn if file changed outside of Remix + const remixdDialog = () => { + return
This file has been changed outside of Remix IDE.
+ } + + const label = (data: File) => { + return ( +
+ + { data.name } + +
+ ) } const renderFiles = (file: File, index: number) => { if (file.isDirectory) { return ( - <> +
{ } : } - - { (state.focusContext.element === file.path) && + { ((state.focusContext.element === file.path) && (state.focusEdit.element !== file.path)) && { path={file.path} type='folder' /> - } - + } + +
) } else { return ( - <> +
{ editable={state.focusEdit.element === file.path} onBlur={(value) => editModeOff(value)} /> - { (state.focusContext.element === file.path) && + { ((state.focusContext.element === file.path) && (state.focusEdit.element !== file.path)) && { type='file' /> } - +
) } } @@ -561,7 +620,7 @@ export const FileExplorer = (props: FileExplorerProps) => { title={name} menuItems={props.menuItems} addFile={addFile} - createNewFile={createNewFile} + createNewFile={handleNewFileInput} createNewFolder={createNewFolder} files={filesProvider} fileManager={state.fileManager} diff --git a/libs/remix-ui/file-explorer/src/lib/types/index.ts b/libs/remix-ui/file-explorer/src/lib/types/index.ts index 09b24ebd7b..2e18e13154 100644 --- a/libs/remix-ui/file-explorer/src/lib/types/index.ts +++ b/libs/remix-ui/file-explorer/src/lib/types/index.ts @@ -30,7 +30,7 @@ export interface FileExplorerContextMenuProps { createNewFile: (folder?: string) => void, createNewFolder: (parentFolder?: string) => void, deletePath: (path: string) => void, - renamePath: (path: string) => void, + renamePath: (path: string, type: string) => void, hideContextMenu: () => void, pageX: number, pageY: number,