diff --git a/apps/remix-ide-e2e/src/tests/plugin_api.ts b/apps/remix-ide-e2e/src/tests/plugin_api.ts index a05197f4b6..9a4d7b74b2 100644 --- a/apps/remix-ide-e2e/src/tests/plugin_api.ts +++ b/apps/remix-ide-e2e/src/tests/plugin_api.ts @@ -295,7 +295,7 @@ module.exports = { scripts: { isDirectory: true }, tests: { isDirectory: true }, 'README.txt': { isDirectory: false } - }, null, null) + }, null, '/') }, 'Should get all workspaces #group2': async function (browser: NightwatchBrowser) { await clickAndCheckLog(browser, 'filePanel:getWorkspaces', [{name:"default_workspace",isGitRepo:false}, {name:"emptyworkspace",isGitRepo:false}, {name:"testspace",isGitRepo:false}], null, null) diff --git a/apps/remix-ide/src/app/files/fileProvider.js b/apps/remix-ide/src/app/files/fileProvider.js index 1a8639149f..fe8c803bf3 100644 --- a/apps/remix-ide/src/app/files/fileProvider.js +++ b/apps/remix-ide/src/app/files/fileProvider.js @@ -127,7 +127,13 @@ class FileProvider { async createDir (path, cb) { const unprefixedpath = this.removePrefix(path) - const paths = unprefixedpath.split('/') + + await this.forceCreateDir(unprefixedpath) + if (cb) cb() + } + + async forceCreateDir (path) { + const paths = path.split('/') if (paths.length && paths[0] === '') paths.shift() let currentCheck = '' for (const value of paths) { @@ -141,7 +147,6 @@ class FileProvider { } } } - if (cb) cb() } // this will not add a folder as readonly but keep the original url to be able to restore it later diff --git a/apps/remix-ide/src/app/files/workspaceFileProvider.js b/apps/remix-ide/src/app/files/workspaceFileProvider.js index 3fcd635fcf..6193e7b486 100644 --- a/apps/remix-ide/src/app/files/workspaceFileProvider.js +++ b/apps/remix-ide/src/app/files/workspaceFileProvider.js @@ -2,7 +2,6 @@ const EventManager = require('events') const FileProvider = require('./fileProvider') -const pathModule = require('path') class WorkspaceFileProvider extends FileProvider { constructor () { @@ -31,16 +30,10 @@ class WorkspaceFileProvider extends FileProvider { } removePrefix (path) { + if (!path) path = '/' path = path.replace(/^\/|\/$/g, '') // remove first and last slash path = path.replace(/^\.\/+/, '') // remove ./ from start of string if (path.startsWith(this.workspacesPath + '/' + this.workspace)) return path - const splitPath = path.split('/') - - if (splitPath[0] === this.workspace) { - splitPath[0] = this.workspacesPath + '/' + this.workspace - path = splitPath.join('/') - return path - } path = super.removePrefix(path) let ret = this.workspacesPath + '/' + this.workspace + '/' + (path === '/' ? '' : path) @@ -80,8 +73,10 @@ class WorkspaceFileProvider extends FileProvider { async createWorkspace (name) { try { if (!name) name = 'default_workspace' + const path = this.workspacesPath + '/' + name + + await super.forceCreateDir(path) this.setWorkspace(name) - await super.createDir(name) this.event.emit('createWorkspace', name) } catch (e) { throw new Error(e) diff --git a/libs/remix-ui/workspace/src/lib/actions/events.ts b/libs/remix-ui/workspace/src/lib/actions/events.ts index ce3c6982f3..74b767cf73 100644 --- a/libs/remix-ui/workspace/src/lib/actions/events.ts +++ b/libs/remix-ui/workspace/src/lib/actions/events.ts @@ -2,6 +2,7 @@ import { fileDecoration } from '@remix-ui/file-decorators' import { extractParentFromKey } from '@remix-ui/helper' import React from 'react' import { action, WorkspaceTemplate } from '../types' +import { ROOT_PATH } from '../utils/constants' import { displayNotification, displayPopUp, fileAddedSuccess, fileRemovedSuccess, fileRenamedSuccess, folderAddedSuccess, loadLocalhostError, loadLocalhostRequest, loadLocalhostSuccess, removeContextMenuItem, removeFocus, rootFolderChangedSuccess, setContextMenuItem, setMode, setReadOnlyMode, setFileDecorationSuccess } from './payload' import { addInputField, createWorkspace, deleteWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile } from './workspace' @@ -164,7 +165,7 @@ const fileAdded = async (filePath: string) => { const folderAdded = async (folderPath: string) => { const provider = plugin.fileManager.currentFileProvider() - const path = extractParentFromKey(folderPath) || provider.workspace || provider.type || '' + const path = extractParentFromKey(folderPath) || ROOT_PATH const promise = new Promise((resolve) => { provider.resolveDirectory(path, (error, fileTree) => { @@ -188,7 +189,7 @@ const fileRemoved = async (removePath: string) => { const fileRenamed = async (oldPath: string) => { const provider = plugin.fileManager.currentFileProvider() - const path = extractParentFromKey(oldPath) || provider.workspace || provider.type || '' + const path = extractParentFromKey(oldPath) || ROOT_PATH const promise = new Promise((resolve) => { provider.resolveDirectory(path, (error, fileTree) => { if (error) console.error(error) diff --git a/libs/remix-ui/workspace/src/lib/actions/workspace.ts b/libs/remix-ui/workspace/src/lib/actions/workspace.ts index 221e0e1a09..3ef203644e 100644 --- a/libs/remix-ui/workspace/src/lib/actions/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/actions/workspace.ts @@ -7,6 +7,7 @@ import { checkSlash, checkSpecialChars } from '@remix-ui/helper' import { JSONStandardInput, WorkspaceTemplate } from '../types' import { QueryParams } from '@remix-project/remix-lib' import * as templateWithContent from '@remix-project/remix-ws-templates' +import { ROOT_PATH } from '../utils/constants' const LOCALHOST = ' - connect to localhost - ' @@ -346,7 +347,7 @@ export const cloneRepository = async (url: string) => { const isActive = await plugin.call('manager', 'isActive', 'dgit') if (!isActive) await plugin.call('manager', 'activatePlugin', 'dgit') - await fetchWorkspaceDirectory(repoName) + await fetchWorkspaceDirectory(ROOT_PATH) dispatch(cloneRepositorySuccess()) }).catch(() => { const cloneModal = { 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 d8f9f01a37..131babab53 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -11,6 +11,7 @@ import { checkSpecialChars, extractNameFromKey, extractParentFromKey, joinPath } // eslint-disable-next-line @typescript-eslint/no-unused-vars import { FileRender } from './file-render' import { Drag } from "@remix-ui/drag-n-drop" +import { ROOT_PATH } from '../utils/constants' export const FileExplorer = (props: FileExplorerProps) => { const { name, contextMenuItems, removedContextMenuItems, files, fileState } = props @@ -32,7 +33,7 @@ export const FileExplorer = (props: FileExplorerProps) => { }, mouseOverElement: null, showContextMenu: false, - reservedKeywords: [name, 'gist-'], + reservedKeywords: [ROOT_PATH, 'gist-'], copyElement: [] }) const [canPaste, setCanPaste] = useState(false) @@ -137,14 +138,14 @@ export const FileExplorer = (props: FileExplorerProps) => { if (props.focusElement[0]) { if (props.focusElement[0].type === 'folder' && props.focusElement[0].key) return props.focusElement[0].key else if (props.focusElement[0].type === 'gist' && props.focusElement[0].key) return props.focusElement[0].key - else if (props.focusElement[0].type === 'file' && props.focusElement[0].key) return extractParentFromKey(props.focusElement[0].key) ? extractParentFromKey(props.focusElement[0].key) : name - else return name + else if (props.focusElement[0].type === 'file' && props.focusElement[0].key) return extractParentFromKey(props.focusElement[0].key) ? extractParentFromKey(props.focusElement[0].key) : ROOT_PATH + else return ROOT_PATH } } const createNewFile = async (newFilePath: string) => { try { - props.dispatchCreateNewFile(newFilePath, props.name) + props.dispatchCreateNewFile(newFilePath, ROOT_PATH) } catch (error) { return props.modal('File Creation Failed', typeof error === 'string' ? error : error.message, 'Close', async () => {}) } @@ -152,7 +153,7 @@ export const FileExplorer = (props: FileExplorerProps) => { const createNewFolder = async (newFolderPath: string) => { try { - props.dispatchCreateNewFolder(newFolderPath, props.name) + props.dispatchCreateNewFolder(newFolderPath, ROOT_PATH) } catch (e) { return props.modal('Folder Creation Failed', typeof e === 'string' ? e : e.message, 'Close', async () => {}) } @@ -174,10 +175,9 @@ export const FileExplorer = (props: FileExplorerProps) => { } const uploadFile = (target) => { - let parentFolder = getFocusedFolder() + const parentFolder = getFocusedFolder() const expandPath = [...new Set([...props.expandPath, parentFolder])] - parentFolder = parentFolder === name ? '/' : parentFolder props.dispatchHandleExpandPath(expandPath) props.dispatchUploadFile(target, parentFolder) } @@ -235,7 +235,6 @@ export const FileExplorer = (props: FileExplorerProps) => { } const handleClickFile = (path: string, type: 'folder' | 'file' | 'gist') => { - path = path.indexOf(props.name + '/') === 0 ? path.replace(props.name + '/', '') : path if (!state.ctrlKey) { props.dispatchHandleClickFile(path, type) } else { @@ -379,7 +378,7 @@ export const FileExplorer = (props: FileExplorerProps) => { } const handlePasteClick = (dest: string, destType: string) => { - dest = destType === 'file' ? extractParentFromKey(dest) || props.name : dest + dest = destType === 'file' ? extractParentFromKey(dest) || ROOT_PATH : dest state.copyElement.map(({ key, type }) => { type === 'file' ? copyFile(key, dest) : copyFolder(key, dest) }) @@ -402,10 +401,10 @@ export const FileExplorer = (props: FileExplorerProps) => { if (e && (e.target as any).getAttribute('data-id') === 'fileExplorerFileUpload') return // we don't want to let propagate the input of type file let expandPath = [] - if (!props.expandPath.includes(props.name)) { - expandPath = [props.name, ...new Set([...props.expandPath])] + if (!props.expandPath.includes(ROOT_PATH)) { + expandPath = [ROOT_PATH, ...new Set([...props.expandPath])] } else { - expandPath = [...new Set(props.expandPath.filter(key => key && (typeof key === 'string') && !key.startsWith(props.name)))] + expandPath = [...new Set(props.expandPath.filter(key => key && (typeof key === 'string')))] } props.dispatchHandleExpandPath(expandPath) } @@ -447,8 +446,8 @@ export const FileExplorer = (props: FileExplorerProps) => {