Commit 0b6579f4 authored by ioedeveloper's avatar ioedeveloper

Export remaining file-explorer functions to actions

parent 39d47a4a
......@@ -25,7 +25,6 @@ export interface File {
export interface FileExplorerMenuProps {
title: string,
menuItems: string[],
fileManager: any,
createNewFile: (folder?: string) => void,
createNewFolder: (parentFolder?: string) => void,
publishToGist: (path?: string) => void,
......@@ -58,10 +57,6 @@ export interface FileExplorerContextMenuProps {
}
export interface FileExplorerState {
focusElement: {
key: string
type: 'folder' | 'file' | 'gist'
}[]
ctrlKey: boolean
newFileName: string
actions: {
......
......@@ -20,9 +20,9 @@ export const checkSlash = (name: string) => {
return name.match(/\//) != null
}
export const createNonClashingNameAsync = async (name, fileManager, prefix = '') => {
export const createNonClashingNameAsync = async (name: string, fileManager, prefix = '') => {
if (!name) name = 'Undefined'
let counter
let _counter
let ext = 'sol'
const reg = /(.*)\.([^.]+)/g
const split = reg.exec(name)
......@@ -33,11 +33,30 @@ export const createNonClashingNameAsync = async (name, fileManager, prefix = '')
let exist = true
do {
const isDuplicate = await fileManager.exists(name + counter + prefix + '.' + ext)
const isDuplicate = await fileManager.exists(name + _counter + prefix + '.' + ext)
if (isDuplicate) counter = (counter | 0) + 1
if (isDuplicate) _counter = (_counter | 0) + 1
else exist = false
} while (exist)
const counter = _counter || ''
return name + counter + prefix + '.' + ext
}
export const joinPath = (...paths) => {
paths = paths.filter((value) => value !== '').map((path) => path.replace(/^\/|\/$/g, '')) // remove first and last slash)
if (paths.length === 1) return paths[0]
return paths.join('/')
}
export const getPathIcon = (path: string) => {
return path.endsWith('.txt')
? 'far fa-file-alt' : path.endsWith('.md')
? 'far fa-file-alt' : path.endsWith('.sol')
? 'fak fa-solidity-mono' : path.endsWith('.js')
? 'fab fa-js' : path.endsWith('.json')
? 'fas fa-brackets-curly' : path.endsWith('.vy')
? 'fak fa-vyper-mono' : path.endsWith('.lex')
? 'fak fa-lexon' : path.endsWith('.contract')
? 'fab fa-ethereum' : 'far fa-file'
}
......@@ -3,6 +3,7 @@ import { bufferToHex, keccakFromString } from 'ethereumjs-util'
import axios, { AxiosResponse } from 'axios'
import { checkSpecialChars, checkSlash, extractParentFromKey, extractNameFromKey, createNonClashingNameAsync } from '@remix-ui/helper'
import Gists from 'gists'
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel/type'
const QueryParams = require('../../../../../../apps/remix-ide/src/lib/query-params')
const examples = require('../../../../../../apps/remix-ide/src/app/editor/examples')
......@@ -194,6 +195,13 @@ const hidePopUp = () => {
}
}
const focusElement = (elements: { key: string, type: 'file' | 'folder' | 'gist' }[]) => {
return {
type: 'SET_FOCUS_ELEMENT',
payload: elements
}
}
const createWorkspaceTemplate = async (workspaceName: string, setDefaults = true, template: 'gist-template' | 'code-template' | 'default-template' = 'default-template') => {
if (!workspaceName) throw new Error('workspace name cannot be empty')
if (checkSpecialChars(workspaceName) || checkSlash(workspaceName)) throw new Error('special characters are not allowed')
......@@ -765,9 +773,95 @@ export const createNewFile = (path: string, rootDir: string) => async (dispatch:
const path = newName.indexOf(rootDir + '/') === 0 ? newName.replace(rootDir + '/', '') : newName
await fileManager.open(path)
setFocusElement([{ key: path, type: 'file' }])(dispatch)
}
}
export const setFocusElement = (elements: { key: string, type: 'file' | 'folder' | 'gist' }[]) => async (dispatch: React.Dispatch<any>) => {
dispatch(focusElement(elements))
}
export const createNewFolder = (path: string, rootDir: string) => async (dispatch: React.Dispatch<any>) => {
const fileManager = plugin.fileManager
const dirName = path + '/'
const exists = await fileManager.exists(dirName)
if (exists) {
return dispatch(displayNotification('Rename File Failed', `A file or folder ${extractNameFromKey(path)} already exists at this location. Please choose a different name.`, 'Close', null, () => {}))
}
await fileManager.mkdir(dirName)
path = path.indexOf(rootDir + '/') === 0 ? path.replace(rootDir + '/', '') : path
dispatch(focusElement([{ key: path, type: 'folder' }]))
}
export const deletePath = (path: string[]) => async (dispatch: React.Dispatch<any>) => {
const fileManager = plugin.fileManager
for (const p of path) {
try {
await fileManager.remove(p)
} catch (e) {
const isDir = await fileManager.isDirectory(p)
dispatch(displayPopUp(`Failed to remove ${isDir ? 'folder' : 'file'} ${p}.`))
}
}
}
export const renamePath = (oldPath: string, newPath: string) => async (dispatch: React.Dispatch<any>) => {
const fileManager = plugin.fileManager
const exists = await fileManager.exists(newPath)
if (exists) {
dispatch(displayNotification('Rename File Failed', `A file or folder ${extractNameFromKey(newPath)} already exists at this location. Please choose a different name.`, 'Close', null, () => {}))
} else {
await fileManager.rename(oldPath, newPath)
}
}
export const copyFile = (src: string, dest: string) => async (dispatch: React.Dispatch<any>) => {
const fileManager = plugin.fileManager
try {
fileManager.copyFile(src, dest)
} catch (error) {
console.log('Oops! An error ocurred while performing copyFile operation.' + error)
dispatch(displayPopUp('Oops! An error ocurred while performing copyFile operation.' + error))
}
}
export const copyFolder = (src: string, dest: string) => async (dispatch: React.Dispatch<any>) => {
const fileManager = plugin.fileManager
try {
fileManager.copyDir(src, dest)
} catch (error) {
console.log('Oops! An error ocurred while performing copyDir operation.' + error)
dispatch(displayPopUp('Oops! An error ocurred while performing copyDir operation.' + error))
}
}
export const runScript = (path: string) => async (dispatch: React.Dispatch<any>) => {
const provider = plugin.fileManager.currentFileProvider()
provider.get(path, (error, content: string) => {
if (error) {
dispatch(displayPopUp(error))
return console.log(error)
}
plugin.call('scriptRunner', 'execute', content)
})
}
export const emitContextMenuEvent = (cmd: customAction) => async () => {
plugin.call(cmd.id, cmd.name, cmd)
}
export const handleClickFile = (path: string, type: 'file' | 'folder' | 'gist') => async (dispatch: React.Dispatch<any>) => {
plugin.fileManager.open(path)
dispatch(focusElement([{ key: path, type }]))
}
const fileAdded = async (filePath: string) => {
await dispatch(fileAddedSuccess(filePath))
if (filePath.includes('_test.sol')) {
......
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel/type'
import { createContext, SyntheticEvent } from 'react'
import { BrowserState } from '../reducers/workspace'
......@@ -16,5 +17,14 @@ export const FileSystemContext = createContext<{
dispatchDeleteWorkspace: (workspaceName: string) => Promise<void>,
dispatchPublishToGist: (path?: string, type?: string) => Promise<void>,
dispatchUploadFile: (target?: SyntheticEvent, targetFolder?: string) => Promise<void>,
dispatchCreateNewFile: (path: string, rootDir: string) => Promise<void>
dispatchCreateNewFile: (path: string, rootDir: string) => Promise<void>,
dispatchSetFocusElement: (elements: { key: string, type: 'file' | 'folder' | 'gist' }[]) => Promise<void>,
dispatchCreateNewFolder: (path: string, rootDir: string) => Promise<void>,
dispatchDeletePath: (path: string[]) => Promise<void>,
dispatchRenamePath: (oldPath: string, newPath: string) => Promise<void>,
dispatchCopyFile: (src: string, dest: string) => Promise<void>,
dispatchCopyFolder: (src: string, dest: string) => Promise<void>,
dispatchRunScript: (path: string) => Promise<void>,
dispatchEmitContextMenuEvent: (cmd: customAction) => Promise<void>,
dispatchHandleClickFile: (path: string, type: 'file' | 'folder' | 'gist') => Promise<void>
}>(null)
......@@ -5,10 +5,11 @@ import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { FileSystemContext } from '../contexts'
import { browserReducer, browserInitialState } from '../reducers/workspace'
import { initWorkspace, fetchDirectory, addInputField, removeInputField, createWorkspace, fetchWorkspaceDirectory, switchToWorkspace, renameWorkspace, deleteWorkspace, clearPopUp, publishToGist, uploadFile, createNewFile } from '../actions/workspace'
import { initWorkspace, fetchDirectory, addInputField, removeInputField, createWorkspace, fetchWorkspaceDirectory, switchToWorkspace, renameWorkspace, deleteWorkspace, clearPopUp, publishToGist, uploadFile, createNewFile, setFocusElement, createNewFolder, deletePath, renamePath, copyFile, copyFolder, runScript, emitContextMenuEvent, handleClickFile } from '../actions/workspace'
import { Modal, WorkspaceProps } from '../types'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { Workspace } from '../remix-ui-workspace'
import { customAction } from '@remixproject/plugin-api/lib/file-system/file-panel/type'
export const FileSystemProvider = (props: WorkspaceProps) => {
const { plugin } = props
......@@ -74,6 +75,42 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
await createNewFile(path, rootDir)(fsDispatch)
}
const dispatchSetFocusElement = async (elements: { key: string, type: 'file' | 'folder' | 'gist' }[]) => {
await setFocusElement(elements)(fsDispatch)
}
const dispatchCreateNewFolder = async (path: string, rootDir: string) => {
await createNewFolder(path, rootDir)(fsDispatch)
}
const dispatchDeletePath = async (path: string[]) => {
await deletePath(path)(fsDispatch)
}
const dispatchRenamePath = async (oldPath: string, newPath: string) => {
await renamePath(oldPath, newPath)(fsDispatch)
}
const dispatchCopyFile = async (src: string, dest: string) => {
await copyFile(src, dest)(fsDispatch)
}
const dispatchCopyFolder = async (src: string, dest: string) => {
await copyFolder(src, dest)(fsDispatch)
}
const dispatchRunScript = async (path: string) => {
await runScript(path)(fsDispatch)
}
const dispatchEmitContextMenuEvent = async (cmd: customAction) => {
await emitContextMenuEvent(cmd)
}
const dispatchHandleClickFile = async (path: string, type: 'file' | 'folder' | 'gist') => {
await handleClickFile(path, type)
}
useEffect(() => {
if (modals.length > 0) {
setFocusModal(() => {
......@@ -159,7 +196,16 @@ export const FileSystemProvider = (props: WorkspaceProps) => {
dispatchDeleteWorkspace,
dispatchPublishToGist,
dispatchUploadFile,
dispatchCreateNewFile
dispatchCreateNewFile,
dispatchSetFocusElement,
dispatchCreateNewFolder,
dispatchDeletePath,
dispatchRenamePath,
dispatchCopyFile,
dispatchCopyFolder,
dispatchRunScript,
dispatchEmitContextMenuEvent,
dispatchHandleClickFile
}
return (
<FileSystemContext.Provider value={value}>
......
......@@ -33,7 +33,8 @@ export interface BrowserState {
},
readonly: boolean,
popup: string,
focusEdit: string
focusEdit: string,
focusElement: { key: string, type: 'file' | 'folder' | 'gist' }[]
}
export const browserInitialState: BrowserState = {
......@@ -65,7 +66,8 @@ export const browserInitialState: BrowserState = {
},
readonly: false,
popup: '',
focusEdit: ''
focusEdit: '',
focusElement: []
}
export const browserReducer = (state = browserInitialState, action: Action) => {
......@@ -453,6 +455,15 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
}
case 'SET_FOCUS_ELEMENT': {
const payload = action.payload as { key: string, type: 'file' | 'folder' | 'gist' }[]
return {
...state,
focusElement: payload
}
}
default:
throw new Error()
}
......
......@@ -45,12 +45,6 @@ export function Workspace (props: WorkspaceProps) {
}
}, [global.fs.browser.workspaces])
props.plugin.resetNewFile = () => {
setState(prevState => {
return { ...prevState, displayNewFile: !state.displayNewFile }
})
}
/* implement an external API, consumed by the parent */
props.plugin.request.createWorkspace = () => {
return createWorkspace()
......@@ -73,18 +67,6 @@ export function Workspace (props: WorkspaceProps) {
return { name: currentWorkspace, isLocalhost: currentWorkspace === LOCALHOST, absolutePath: `${props.plugin.workspace.workspacesPath}/${currentWorkspace}` }
}
const createNewWorkspace = async (workspaceName) => {
try {
await props.plugin.fileManager.closeAllFiles()
await props.plugin.createWorkspace(workspaceName)
await setWorkspace(workspaceName)
global.toast('New default workspace has been created.')
} catch (e) {
global.modal('Create Default Workspace', e.message, 'OK', onFinishRenameWorkspace, '')
console.error(e)
}
}
/* workspace creation, renaming and deletion */
const renameCurrentWorkspace = () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment