diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index e24680e91fa..ca4d6eab285 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -713,7 +713,7 @@ class FileManager extends Plugin { } try { // This make sure dependencies are loaded in the editor context. - // This ensure monaco is aware of deps artifacts, so it can provide basic features like "go to" symbols. + // This ensure monaco is aware of deps artifacts, so it can provide basic features like "go to" symbols. await this.editor.handleTypeScriptDependenciesOf(file, content, path => this.readFile(path), path => this.exists(path)) } catch (e) { console.log('unable to handle TypeScript dependencies of', file) diff --git a/libs/remix-ui/workspace/src/lib/actions/index.ts b/libs/remix-ui/workspace/src/lib/actions/index.ts index f7c5098426b..2e762c07193 100644 --- a/libs/remix-ui/workspace/src/lib/actions/index.ts +++ b/libs/remix-ui/workspace/src/lib/actions/index.ts @@ -142,7 +142,6 @@ export const initWorkspace = (filePanelPlugin) => async (reducerDispatch: React. } export const fetchDirectory = async (path: string) => { - console.trace() const provider = plugin.fileManager.currentFileProvider() const promise = new Promise((resolve) => { provider.resolveDirectory(path, (error, fileTree) => { diff --git a/libs/remix-ui/workspace/src/lib/actions/payload.ts b/libs/remix-ui/workspace/src/lib/actions/payload.ts index ea804ce2d17..a8d5e168be4 100644 --- a/libs/remix-ui/workspace/src/lib/actions/payload.ts +++ b/libs/remix-ui/workspace/src/lib/actions/payload.ts @@ -140,17 +140,17 @@ export const fetchWorkspaceDirectoryError = (error: any) => { } } -export const fetchWorkspaceDirectoryRequest = (promise: Promise) => { +export const fetchWorkspaceDirectoryRequest = (promise: Promise, direction?: 'asc' | 'desc') => { return { type: 'FETCH_WORKSPACE_DIRECTORY_REQUEST', - payload: promise + payload: { promise, direction } } } -export const fetchWorkspaceDirectorySuccess = (path: string, fileTree) => { +export const fetchWorkspaceDirectorySuccess = (path: string, fileTree, direction?: 'asc' | 'desc') => { return { type: 'FETCH_WORKSPACE_DIRECTORY_SUCCESS', - payload: { path, fileTree } + payload: { path, fileTree, direction } } } diff --git a/libs/remix-ui/workspace/src/lib/actions/workspace.ts b/libs/remix-ui/workspace/src/lib/actions/workspace.ts index 37652f1b049..bfa484a23e1 100644 --- a/libs/remix-ui/workspace/src/lib/actions/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/actions/workspace.ts @@ -266,7 +266,7 @@ export const workspaceExists = async (name: string) => { return await browserProvider.exists(workspacePath) } -export const fetchWorkspaceDirectory = async (path: string) => { +export const fetchWorkspaceDirectory = async (path: string, direction?: 'asc' | 'desc') => { if (!path) return const provider = plugin.fileManager.currentFileProvider() const promise = new Promise((resolve) => { @@ -277,9 +277,9 @@ export const fetchWorkspaceDirectory = async (path: string) => { }) }) - dispatch(fetchWorkspaceDirectoryRequest(promise)) + dispatch(fetchWorkspaceDirectoryRequest(promise, direction)) promise.then((fileTree) => { - dispatch(fetchWorkspaceDirectorySuccess(path, fileTree)) + dispatch(fetchWorkspaceDirectorySuccess(path, fileTree, direction)) }).catch((error) => { dispatch(fetchWorkspaceDirectoryError({ error })) }) @@ -683,7 +683,7 @@ const scriptsRef = { 'etherscan': etherscanScripts } export const createHelperScripts = async (script: string) => { - + if (!scriptsRef[script]) return await scriptsRef[script](plugin) plugin.call('notification', 'toast', 'scripts added in the "scripts" folder') 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 d65d88fa75e..d2722b99ca2 100644 --- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx +++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx @@ -18,6 +18,10 @@ export const FileExplorer = (props: FileExplorerProps) => { contextMenuItems, removedContextMenuItems, files, + sortIconDesc, + sortIconAsc, + sortIcon, + setSortIcon, workspaceState, toGist, addMenuItems, @@ -29,12 +33,8 @@ export const FileExplorer = (props: FileExplorerProps) => { uploadFolder, fileState } = props - const sortIconDesc = 'fa fa-sort-alpha-desc justify-end' - const sortIconAsc = 'fa fa-sort-alpha-up justify-end' const [state, setState] = useState(workspaceState) - const [sortIcon, setSortIcon] = useState(sortIconDesc) const treeRef = useRef(null) - console.log({ props }) useEffect(() => { if (contextMenuItems) { @@ -307,9 +307,13 @@ export const FileExplorer = (props: FileExplorerProps) => { tooltipText={} > { - console.log('sorting clicked') - sortIcon === sortIconDesc ? setSortIcon(sortIconAsc) : setSortIcon(sortIconDesc) - props.dispatchDirectoriesSort(files[ROOT_PATH]) + if(sortIcon === sortIconAsc) { + setSortIcon(sortIconDesc) + props.setTriggerSort('desc') + } else { + setSortIcon(sortIconAsc) + props.setTriggerSort('asc') + } }}> diff --git a/libs/remix-ui/workspace/src/lib/contexts/index.ts b/libs/remix-ui/workspace/src/lib/contexts/index.ts index 5eb61aa8a1f..ebf04c47a95 100644 --- a/libs/remix-ui/workspace/src/lib/contexts/index.ts +++ b/libs/remix-ui/workspace/src/lib/contexts/index.ts @@ -13,8 +13,7 @@ export const FileSystemContext = createContext<{ dispatchRemoveInputField:(path: string) => Promise, dispatchCreateWorkspace: (workspaceName: string, workspaceTemplateName: string, opts?, initGitRepo?: boolean) => Promise, toast: (toasterMsg: string) => void, - dispatchFetchWorkspaceDirectory: (path: string) => Promise, - dispatchDirectoriesSort: (files: { [x: string]: Record } | any, direction?: 'asc' | 'desc') => Promise, + dispatchFetchWorkspaceDirectory: (path: string, direction?: 'asc' | 'desc') => Promise, dispatchSwitchToWorkspace: (name: string) => Promise, dispatchRenameWorkspace: (oldName: string, workspaceName: string) => Promise, dispatchDeleteWorkspace: (workspaceName: string) => Promise, diff --git a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx index 1a534a0e81f..78d4afc89e5 100644 --- a/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx +++ b/libs/remix-ui/workspace/src/lib/providers/FileSystemProvider.tsx @@ -76,11 +76,6 @@ export const FileSystemProvider = (props: WorkspaceProps) => { await fetchDirectory(path) } - const dispatchDirectoriesSort = async (files: any, path?: string, direction?: 'asc' | 'desc') => { - const result = await fetchDirectory(files.path ?? path) - console.log(result) - } - const dispatchAddInputField = async (path: string, type: 'file' | 'folder') => { await addInputField(type, path) } @@ -93,8 +88,8 @@ export const FileSystemProvider = (props: WorkspaceProps) => { await createWorkspace(workspaceName, workspaceTemplateName, opts, null, null, initGitRepo) } - const dispatchFetchWorkspaceDirectory = async (path: string) => { - await fetchWorkspaceDirectory(path) + const dispatchFetchWorkspaceDirectory = async (path: string, direction?: 'asc' | 'desc') => { + await fetchWorkspaceDirectory(path, direction) } const dispatchSwitchToWorkspace = async (name: string) => { @@ -310,7 +305,6 @@ export const FileSystemProvider = (props: WorkspaceProps) => { toast, dispatchInitWorkspace, dispatchFetchDirectory, - dispatchDirectoriesSort, dispatchAddInputField, dispatchRemoveInputField, dispatchCreateWorkspace, diff --git a/libs/remix-ui/workspace/src/lib/reducers/workspace.ts b/libs/remix-ui/workspace/src/lib/reducers/workspace.ts index 9cec5c880c8..908cd15691d 100644 --- a/libs/remix-ui/workspace/src/lib/reducers/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/reducers/workspace.ts @@ -10,6 +10,7 @@ interface Action { export interface BrowserState { browser: { currentWorkspace: string + sort?: 'asc' | 'desc', workspaces: { name: string isGitRepo: boolean @@ -71,6 +72,7 @@ export interface BrowserState { export const browserInitialState: BrowserState = { browser: { currentWorkspace: '', + sort: null, workspaces: [], files: {}, expandPath: [], @@ -255,12 +257,13 @@ export const browserReducer = (state = browserInitialState, action: Action) => { } case 'FETCH_WORKSPACE_DIRECTORY_SUCCESS': { - const payload = action.payload as {path: string; fileTree} + const payload = action.payload as {path: string; fileTree, direction?: 'asc' | 'desc'} return { ...state, browser: { ...state.browser, + sort: payload.direction ?? 'asc', files: state.mode === 'browser' ? fetchWorkspaceDirectoryContent(state, payload) @@ -934,15 +937,9 @@ const removeInputField = ( } const sortFilesFetched = (folderStructure: any, direction?: 'asc' | 'desc') => { - // eslint-disable-next-line prefer-const - let newResult = _.fromPairs( - direction && direction === 'desc' ? _.sortBy(_.toPairs(folderStructure[ROOT_PATH]), (x: any) => x[1].name).reverse() : _.sortBy(_.toPairs(folderStructure[ROOT_PATH]), (x: any) => x[1].name)) - let target = {} - Object.assign(target, newResult) - const result = { '/': target } - target = null - newResult = null - return result + const newResult = direction && direction === 'desc' ? _.fromPairs(_.sortBy(_.toPairs(folderStructure), (x: any) => x[0]).reverse()) + : _.fromPairs(_.sortBy(_.toPairs(folderStructure), (x: any) => x[0])) + return Object.assign({}, newResult) } // IDEA: Modify function to remove blank input field without fetching content @@ -951,14 +948,13 @@ const fetchDirectoryContent = ( payload: {fileTree; path: string; type?: 'file' | 'folder'}, deletePath?: string ): {[x: string]: Record} => { - // console.trace() if (!payload.fileTree) return state.mode === 'browser' ? state.browser.files : state[state.mode].files if (state.mode === 'browser') { if (payload.path === ROOT_PATH) { - let files = normalize(payload.fileTree, ROOT_PATH, payload.type) + let files = normalize(payload.fileTree, ROOT_PATH, payload.type, state) files = _.merge(files, state.browser.files[ROOT_PATH]) if (deletePath) delete files[deletePath] return {[ROOT_PATH]: files} @@ -979,7 +975,7 @@ const fetchDirectoryContent = ( if (prevFiles) { prevFiles.child = _.merge( - normalize(payload.fileTree, payload.path, payload.type), + normalize(payload.fileTree, payload.path, payload.type, state), prevFiles.child ) if (deletePath) { @@ -995,7 +991,8 @@ const fetchDirectoryContent = ( [payload.path]: normalize( payload.fileTree, payload.path, - payload.type + payload.type, + state ) } } @@ -1015,7 +1012,7 @@ const fetchDirectoryContent = ( if (prevFiles) { prevFiles.child = _.merge( - normalize(payload.fileTree, payload.path, payload.type), + normalize(payload.fileTree, payload.path, payload.type, state), prevFiles.child ) if (deletePath) { @@ -1031,7 +1028,8 @@ const fetchDirectoryContent = ( [payload.path]: normalize( payload.fileTree, payload.path, - payload.type + payload.type, + state ) } } @@ -1044,7 +1042,7 @@ const fetchWorkspaceDirectoryContent = ( state: BrowserState, payload: {fileTree; path: string} ): {[x: string]: Record} => { - const files = normalize(payload.fileTree, ROOT_PATH) + const files = normalize(payload.fileTree, ROOT_PATH, null, state) return {[ROOT_PATH]: files} } @@ -1052,10 +1050,11 @@ const fetchWorkspaceDirectoryContent = ( const normalize = ( filesList, directory?: string, - newInputType?: 'folder' | 'file' + newInputType?: 'folder' | 'file', + state?: BrowserState ): Record => { - const folders = {} - const files = {} + let folders = {} + let files = {} Object.keys(filesList || {}).forEach((key) => { key = key.replace(/^\/|\/$/g, '') // remove first and last slash @@ -1099,7 +1098,8 @@ const normalize = ( type: 'file' } } - + folders = sortFilesFetched(folders, state.browser.sort) + files = sortFilesFetched(files, state.browser.sort) return Object.assign({}, folders, files) } diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index 821e39220c3..f22b78871ea 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -8,10 +8,13 @@ import './css/remix-ui-workspace.css' import {ROOT_PATH, TEMPLATE_NAMES} from './utils/constants' import {HamburgerMenu} from './components/workspace-hamburger' -import {MenuItems, WorkSpaceState} from './types' +import {FileType, MenuItems, WorkSpaceState} from './types' import {contextMenuActions} from './utils' import FileExplorerContextMenu from './components/file-explorer-context-menu' import {customAction} from '@remixproject/plugin-api' +import * as _ from 'lodash' + + const _paq = (window._paq = window._paq || []) @@ -46,9 +49,11 @@ export function Workspace() { const initGitRepoRef = useRef() const filteredBranches = selectedWorkspace ? (selectedWorkspace.branches || []).filter((branch) => branch.name.includes(branchFilter) && branch.name !== 'HEAD').slice(0, 20) : [] const currentBranch = selectedWorkspace ? selectedWorkspace.currentBranch : null - + const sortIconDesc = 'fa fa-sort-alpha-desc justify-end' + const sortIconAsc = 'fa fa-sort-alpha-up justify-end' + const [sortIcon, setSortIcon] = useState(sortIconDesc) + const [triggerSort, setTriggerSort] = useState<'asc' | 'desc'>(null) const [canPaste, setCanPaste] = useState(false) - const [state, setState] = useState({ ctrlKey: false, newFileName: '', @@ -126,6 +131,10 @@ export function Workspace() { } }, [global.fs.browser.currentWorkspace, global.fs.localhost.sharedFolder, global.fs.mode]) + useEffect(() => { + global.dispatchFetchWorkspaceDirectory(ROOT_PATH, triggerSort) + }, [triggerSort]) + useEffect(() => { if (global.fs.browser.currentWorkspace && !global.fs.browser.workspaces.find(({name}) => name === global.fs.browser.currentWorkspace)) { if (global.fs.browser.workspaces.length > 0) { @@ -965,6 +974,12 @@ export function Workspace() { contextMenuItems={global.fs.browser.contextMenu.registeredMenuItems} removedContextMenuItems={global.fs.browser.contextMenu.removedMenuItems} files={global.fs.browser.files} + triggerSort={triggerSort} + setTriggerSort={setTriggerSort} + sortIcon={sortIcon} + sortIconAsc={sortIconAsc} + sortIconDesc={sortIconDesc} + setSortIcon={setSortIcon} workspaceState={state} expandPath={global.fs.browser.expandPath} focusEdit={global.fs.focusEdit} @@ -989,7 +1004,6 @@ export function Workspace() { dispatchHandleClickFile={global.dispatchHandleClickFile} dispatchSetFocusElement={global.dispatchSetFocusElement} dispatchFetchDirectory={global.dispatchFetchDirectory} - dispatchDirectoriesSort={global.dispatchDirectoriesSort} dispatchRemoveInputField={global.dispatchRemoveInputField} dispatchAddInputField={global.dispatchAddInputField} dispatchHandleExpandPath={global.dispatchHandleExpandPath} @@ -1023,6 +1037,12 @@ export function Workspace() { contextMenuItems={global.fs.localhost.contextMenu.registeredMenuItems} removedContextMenuItems={global.fs.localhost.contextMenu.removedMenuItems} files={global.fs.localhost.files} + triggerSort={triggerSort} + setTriggerSort={setTriggerSort} + sortIcon={sortIcon} + sortIconAsc={sortIconAsc} + sortIconDesc={sortIconDesc} + setSortIcon={setSortIcon} fileState={[]} workspaceState={state} expandPath={global.fs.localhost.expandPath} @@ -1048,7 +1068,6 @@ export function Workspace() { dispatchHandleClickFile={global.dispatchHandleClickFile} dispatchSetFocusElement={global.dispatchSetFocusElement} dispatchFetchDirectory={global.dispatchFetchDirectory} - dispatchDirectoriesSort={global.dispatchDirectoriesSort} dispatchRemoveInputField={global.dispatchRemoveInputField} dispatchAddInputField={global.dispatchAddInputField} dispatchHandleExpandPath={global.dispatchHandleExpandPath} diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts index 7776ec86d11..224f5731188 100644 --- a/libs/remix-ui/workspace/src/lib/types/index.ts +++ b/libs/remix-ui/workspace/src/lib/types/index.ts @@ -89,6 +89,12 @@ export interface FileExplorerProps { hideIconsMenu: React.Dispatch>, showIconsMenu: boolean, focusElement: { key: string, type: 'file' | 'folder' | 'gist' }[], + setSortIcon: React.Dispatch>, + triggerSort: 'asc' | 'desc' | null, + setTriggerSort: React.Dispatch>, + sortIcon: string, + sortIconAsc: string, + sortIconDesc: string, dispatchCreateNewFile: (path: string, rootDir: string) => Promise, // eslint-disable-next-line no-undef modal:(title: string, message: string | JSX.Element, okLabel: string, okFn: () => void, cancelLabel?: string, cancelFn?: () => void) => void, @@ -108,7 +114,6 @@ export interface FileExplorerProps { dispatchHandleClickFile: (path: string, type: 'file' | 'folder' | 'gist') => Promise, dispatchSetFocusElement: (elements: { key: string, type: 'file' | 'folder' | 'gist' }[]) => Promise, dispatchFetchDirectory:(path: string) => Promise, - dispatchDirectoriesSort: (files: { [x: string]: Record } | any, direction?: 'asc' | 'desc') => Promise, dispatchRemoveInputField:(path: string) => Promise, dispatchAddInputField:(path: string, type: 'file' | 'folder') => Promise, dispatchHandleExpandPath: (paths: string[]) => Promise, @@ -203,4 +208,4 @@ export type FileFocusContextType = { export type CopyElementType = { key: string type: 'folder' | 'gist' | 'file' | 'workspace' -} + }