Merge branch 'master' into bunsenstraat-patch-1

pull/1210/head
bunsenstraat 4 years ago committed by GitHub
commit 93128aa956
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      apps/remix-ide-e2e/src/tests/gist.spec.ts
  2. 34
      apps/remix-ide/src/app/tabs/runTab/contractDropdown.js
  3. 2
      apps/remix-ide/src/app/tabs/runTab/model/dropdownlogic.js
  4. 26
      apps/remix-ide/src/app/tabs/runTab/settings.js
  5. 8
      apps/remix-ide/src/app/ui/universal-dapp-ui.js
  6. 21
      apps/remix-ide/src/blockchain/blockchain.js
  7. 4
      apps/remix-ide/src/lib/gist-handler.js
  8. 5
      libs/remix-ui/debugger-ui/src/lib/debugger-ui.tsx
  9. 14
      libs/remix-ui/file-explorer/src/lib/actions/fileSystem.ts
  10. 10
      libs/remix-ui/file-explorer/src/lib/file-explorer-context-menu.tsx
  11. 134
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx
  12. 9
      libs/remix-ui/file-explorer/src/lib/reducers/fileSystem.ts
  13. 8
      libs/remix-ui/file-explorer/src/lib/types/index.ts

@ -54,9 +54,9 @@ module.exports = {
.click('[data-id="default_workspace-modal-footer-cancel-react"]') .click('[data-id="default_workspace-modal-footer-cancel-react"]')
.executeScript(`remix.loadgist('${gistid}')`) .executeScript(`remix.loadgist('${gistid}')`)
// .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('gists') } done() }) // .perform((done) => { if (runtimeBrowser === 'chrome') { browser.openFile('gists') } done() })
.waitForElementVisible(`[data-id="treeViewLitreeViewItem${gistid}"]`) .waitForElementVisible(`[data-id="treeViewLitreeViewItem/gist-${gistid}"]`)
.click(`[data-id="treeViewLitreeViewItem${gistid}"]`) .click(`[data-id="treeViewLitreeViewItem/gist-${gistid}"]`)
.openFile(`${gistid}/README.txt`) .openFile(`gist-${gistid}/README.txt`)
} }
}) })
}, },
@ -118,9 +118,9 @@ module.exports = {
.waitForElementVisible('*[data-id="modalDialogCustomPromptText"]') .waitForElementVisible('*[data-id="modalDialogCustomPromptText"]')
.setValue('*[data-id="modalDialogCustomPromptText"]', testData.validGistId) .setValue('*[data-id="modalDialogCustomPromptText"]', testData.validGistId)
.modalFooterOKClick() .modalFooterOKClick()
.openFile(`${testData.validGistId}/ApplicationRegistry`) .openFile(`gist-${testData.validGistId}/ApplicationRegistry`)
.waitForElementVisible(`div[title='default_workspace/${testData.validGistId}/ApplicationRegistry']`) .waitForElementVisible(`div[title='default_workspace/gist-${testData.validGistId}/ApplicationRegistry']`)
.assert.containsText(`div[title='default_workspace/${testData.validGistId}/ApplicationRegistry'] > span`, 'ApplicationRegistry') .assert.containsText(`div[title='default_workspace/gist-${testData.validGistId}/ApplicationRegistry'] > span`, 'ApplicationRegistry')
.end() .end()
} }
} }

@ -48,24 +48,22 @@ class ContractDropdownUI {
} }
listenToContextChange () { listenToContextChange () {
this.blockchain.event.register('contextChanged', () => { this.blockchain.event.register('networkStatus', ({ error, network }) => {
this.blockchain.updateNetwork((err, { name } = {}) => { if (error) {
if (err) { console.log('can\'t detect network')
console.log('can\'t detect network') return
return }
} this.exEnvironment = this.blockchain.getProvider()
this.exEnvironment = this.blockchain.getProvider() this.networkName = network.name
this.networkName = name
const savedConfig = window.localStorage.getItem(`ipfs/${this.exEnvironment}/${this.networkName}`) const savedConfig = window.localStorage.getItem(`ipfs/${this.exEnvironment}/${this.networkName}`)
// check if an already selected option exist else use default workflow // check if an already selected option exist else use default workflow
if (savedConfig !== null) { if (savedConfig !== null) {
this.setCheckedState(savedConfig) this.setCheckedState(savedConfig)
} else { } else {
this.setCheckedState(this.networkName === 'Main') this.setCheckedState(this.networkName === 'Main')
} }
})
}) })
} }
@ -306,10 +304,10 @@ class ContractDropdownUI {
const data = self.runView.compilersArtefacts.getCompilerAbstract(contractObject.contract.file) const data = self.runView.compilersArtefacts.getCompilerAbstract(contractObject.contract.file)
self.runView.compilersArtefacts.addResolvedContract(helper.addressToString(address), data) self.runView.compilersArtefacts.addResolvedContract(helper.addressToString(address), data)
if (self.ipfsCheckedState) { if (self.ipfsCheckedState) {
_paq.push(['trackEvent', 'udapp', `DeployAndPublish_${this.networkName}`]) _paq.push(['trackEvent', 'udapp', 'DeployAndPublish', this.networkName])
publishToStorage('ipfs', self.runView.fileProvider, self.runView.fileManager, selectedContract) publishToStorage('ipfs', self.runView.fileProvider, self.runView.fileManager, selectedContract)
} else { } else {
_paq.push(['trackEvent', 'udapp', `DeployOnly_${this.networkName}`]) _paq.push(['trackEvent', 'udapp', 'DeployOnly', this.networkName])
} }
} }

@ -55,7 +55,7 @@ class DropdownLogic {
cb(null, 'abi', abi) cb(null, 'abi', abi)
}) })
} else { } else {
_paq.push(['trackEvent', 'udapp', 'AtAddressLoadWithInstance']) _paq.push(['trackEvent', 'udapp', 'AtAddressLoadWithArtifacts'])
cb(null, 'instance') cb(null, 'instance')
} }
} }

@ -97,7 +97,7 @@ class SettingsUI {
Environment Environment
</label> </label>
<div class="${css.environment}"> <div class="${css.environment}">
<select id="selectExEnvOptions" data-id="settingsSelectEnvOptions" onchange=${() => { this.updateNetwork() }} class="form-control ${css.select} custom-select"> <select id="selectExEnvOptions" data-id="settingsSelectEnvOptions" class="form-control ${css.select} custom-select">
<option id="vm-mode" <option id="vm-mode"
title="Execution environment does not connect to any node, everything is local and in memory only." title="Execution environment does not connect to any node, everything is local and in memory only."
value="vm" name="executionContext"> JavaScript VM value="vm" name="executionContext"> JavaScript VM
@ -192,8 +192,17 @@ class SettingsUI {
this.setFinalContext() this.setFinalContext()
}) })
this.blockchain.event.register('networkStatus', ({ error, network }) => {
if (error) {
this.netUI.innerHTML = 'can\'t detect network '
return
}
const networkProvider = this._components.networkModule.getNetworkProvider.bind(this._components.networkModule)
this.netUI.innerHTML = (networkProvider() !== 'vm') ? `${network.name} (${network.id || '-'}) network` : ''
})
setInterval(() => { setInterval(() => {
this.updateNetwork() this.fillAccountsList()
}, 1000) }, 1000)
this.el = el this.el = el
@ -273,7 +282,6 @@ class SettingsUI {
// set the final context. Cause it is possible that this is not the one we've originaly selected // set the final context. Cause it is possible that this is not the one we've originaly selected
this.selectExEnv.value = this.blockchain.getProvider() this.selectExEnv.value = this.blockchain.getProvider()
this.event.trigger('clearInstance', []) this.event.trigger('clearInstance', [])
this.updateNetwork()
this.updatePlusButton() this.updatePlusButton()
} }
@ -390,18 +398,6 @@ class SettingsUI {
}) })
} }
updateNetwork () {
this.blockchain.updateNetwork((err, { id, name } = {}) => {
if (err) {
this.netUI.innerHTML = 'can\'t detect network '
return
}
const network = this._components.networkModule.getNetworkProvider.bind(this._components.networkModule)
this.netUI.innerHTML = (network() !== 'vm') ? `${name} (${id || '-'}) network` : ''
})
this.fillAccountsList()
}
// TODO: unclear what's the goal of accountListCallId, feels like it can be simplified // TODO: unclear what's the goal of accountListCallId, feels like it can be simplified
async fillAccountsList () { async fillAccountsList () {
this.accountListCallId++ this.accountListCallId++

@ -244,8 +244,12 @@ UniversalDAppUI.prototype.runTransaction = function (lookupOnly, args, valArr, i
outputOverride.appendChild(decoded) outputOverride.appendChild(decoded)
} }
} }
const info = `${lookupOnly ? 'call' : args.funABI.type !== 'fallback' ? 'lowLevelInteracions' : 'transact'}_${this.blockchain.executionContext.executionContext}` let callinfo = ''
_paq.push(['trackEvent', 'udapp', info]) if (lookupOnly) callinfo = 'call'
else if (args.funABI.type === 'fallback' || args.funABI.type === 'receive') callinfo = 'lowLevelInteracions'
else callinfo = 'transact'
_paq.push(['trackEvent', 'udapp', callinfo, this.blockchain.getCurrentNetworkStatus().network.name])
const params = args.funABI.type !== 'fallback' ? inputsValues : '' const params = args.funABI.type !== 'fallback' ? inputsValues : ''
this.blockchain.runOrCallContractMethod( this.blockchain.runOrCallContractMethod(
args.contractName, args.contractName,

@ -41,6 +41,7 @@ class Blockchain {
this.executionContext.event.register('contextChanged', this.resetEnvironment.bind(this)) this.executionContext.event.register('contextChanged', this.resetEnvironment.bind(this))
this.networkcallid = 0 this.networkcallid = 0
this.networkStatus = { name: ' - ', id: ' - ' }
this.setupEvents() this.setupEvents()
this.setupProviders() this.setupProviders()
} }
@ -57,6 +58,17 @@ class Blockchain {
this.executionContext.event.register('removeProvider', (name) => { this.executionContext.event.register('removeProvider', (name) => {
this.event.trigger('removeProvider', [name]) this.event.trigger('removeProvider', [name])
}) })
setInterval(() => {
this.detectNetwork((error, network) => {
this.networkStatus = { network, error }
this.event.trigger('networkStatus', [this.networkStatus])
})
}, 1000)
}
getCurrentNetworkStatus () {
return this.networkStatus
} }
setupProviders () { setupProviders () {
@ -197,15 +209,6 @@ class Blockchain {
return this.executionContext.setProviderFromEndpoint(target, context, cb) return this.executionContext.setProviderFromEndpoint(target, context, cb)
} }
updateNetwork (cb) {
this.executionContext.detectNetwork((err, { id, name } = {}) => {
if (err) {
return cb(err)
}
cb(null, { id, name })
})
}
detectNetwork (cb) { detectNetwork (cb) {
return this.executionContext.detectNetwork(cb) return this.executionContext.detectNetwork(cb)
} }

@ -54,7 +54,9 @@ function GistHandler (_window) {
} }
const obj = {} const obj = {}
Object.keys(data.files).forEach((element) => { Object.keys(data.files).forEach((element) => {
obj['/' + gistId + '/' + element] = data.files[element] const path = element.replace(/\.\.\./g, '/')
obj['/' + 'gist-' + gistId + '/' + path] = data.files[element]
}) })
fileManager.setBatchFiles(obj, 'workspace', true, (errorLoadingFile) => { fileManager.setBatchFiles(obj, 'workspace', true, (errorLoadingFile) => {
if (!errorLoadingFile) { if (!errorLoadingFile) {

@ -9,6 +9,7 @@ import { Toaster } from '@remix-ui/toaster' // eslint-disable-line
/* eslint-disable-next-line */ /* eslint-disable-next-line */
import './debugger-ui.css' import './debugger-ui.css'
const helper = require('../../../../../apps/remix-ide/src/lib/helper') const helper = require('../../../../../apps/remix-ide/src/lib/helper')
const _paq = (window as any)._paq = (window as any)._paq || []
export const DebuggerUI = (props: DebuggerUIProps) => { export const DebuggerUI = (props: DebuggerUIProps) => {
const debuggerModule = props.debuggerAPI const debuggerModule = props.debuggerAPI
@ -167,7 +168,9 @@ export const DebuggerUI = (props: DebuggerUIProps) => {
const web3 = await debuggerModule.getDebugWeb3() const web3 = await debuggerModule.getDebugWeb3()
try { try {
if (await web3.eth.net.getId() === 42) { const networkId = await web3.eth.net.getId()
_paq.push(['trackEvent', 'debugger', 'startDebugging', networkId])
if (networkId === 42) {
setState(prevState => { setState(prevState => {
return { return {
...prevState, ...prevState,

@ -41,14 +41,16 @@ const normalize = (parent, filesList, newInputType?: string): any => {
if (filesList[key].isDirectory) { if (filesList[key].isDirectory) {
folders[extractNameFromKey(key)] = { folders[extractNameFromKey(key)] = {
path, path,
name: extractNameFromKey(path), name: extractNameFromKey(path).indexOf('gist-') === 0 ? extractNameFromKey(path).split('-')[1] : extractNameFromKey(path),
isDirectory: filesList[key].isDirectory isDirectory: filesList[key].isDirectory,
type: extractNameFromKey(path).indexOf('gist-') === 0 ? 'gist' : 'folder'
} }
} else { } else {
files[extractNameFromKey(key)] = { files[extractNameFromKey(key)] = {
path, path,
name: extractNameFromKey(path), name: extractNameFromKey(path),
isDirectory: filesList[key].isDirectory isDirectory: filesList[key].isDirectory,
type: 'file'
} }
} }
}) })
@ -59,7 +61,8 @@ const normalize = (parent, filesList, newInputType?: string): any => {
folders[path] = { folders[path] = {
path: path, path: path,
name: '', name: '',
isDirectory: true isDirectory: true,
type: 'folder'
} }
} else if (newInputType === 'file') { } else if (newInputType === 'file') {
const path = parent + '/blank' const path = parent + '/blank'
@ -67,7 +70,8 @@ const normalize = (parent, filesList, newInputType?: string): any => {
files[path] = { files[path] = {
path: path, path: path,
name: '', name: '',
isDirectory: false isDirectory: false,
type: 'file'
} }
} }

@ -4,7 +4,7 @@ import { FileExplorerContextMenuProps } from './types'
import './css/file-explorer-context-menu.css' import './css/file-explorer-context-menu.css'
export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => { export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) => {
const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, publishToGist, runScript, emit, pageX, pageY, path, type, ...otherProps } = props const { actions, createNewFile, createNewFolder, deletePath, renamePath, hideContextMenu, pushChangesToGist, publishFileToGist, publishFolderToGist, runScript, emit, pageX, pageY, path, type, ...otherProps } = props
const contextMenuRef = useRef(null) const contextMenuRef = useRef(null)
useEffect(() => { useEffect(() => {
@ -50,7 +50,13 @@ export const FileExplorerContextMenu = (props: FileExplorerContextMenuProps) =>
deletePath(path) deletePath(path)
break break
case 'Push changes to gist': case 'Push changes to gist':
publishToGist() pushChangesToGist(path, type)
break
case 'Publish folder to gist':
publishFolderToGist(path, type)
break
case 'Publish file to gist':
publishFileToGist(path, type)
break break
case 'Run': case 'Run':
runScript(path) runScript(path)

@ -31,14 +31,14 @@ export const FileExplorer = (props: FileExplorerProps) => {
actions: [{ actions: [{
id: 'newFile', id: 'newFile',
name: 'New File', name: 'New File',
type: ['folder'], type: ['folder', 'gist'],
path: [], path: [],
extension: [], extension: [],
pattern: [] pattern: []
}, { }, {
id: 'newFolder', id: 'newFolder',
name: 'New Folder', name: 'New Folder',
type: ['folder'], type: ['folder', 'gist'],
path: [], path: [],
extension: [], extension: [],
pattern: [] pattern: []
@ -52,17 +52,31 @@ export const FileExplorer = (props: FileExplorerProps) => {
}, { }, {
id: 'delete', id: 'delete',
name: 'Delete', name: 'Delete',
type: ['file', 'folder'], type: ['file', 'folder', 'gist'],
path: [], path: [],
extension: [], extension: [],
pattern: [] pattern: []
}, { }, {
id: 'pushChangesToGist', id: 'pushChangesToGist',
name: 'Push changes to gist', name: 'Push changes to gist',
type: [], type: ['gist'],
path: [],
extension: [],
pattern: []
}, {
id: 'publishFolderToGist',
name: 'Publish folder to gist',
type: ['folder'],
path: [], path: [],
extension: [], extension: [],
pattern: ['^browser/gists/([0-9]|[a-z])*$'] pattern: []
}, {
id: 'publishFileToGist',
name: 'Publish file to gist',
type: ['file'],
path: [],
extension: [],
pattern: []
}, { }, {
id: 'run', id: 'run',
name: 'Run', name: 'Run',
@ -228,6 +242,15 @@ export const FileExplorer = (props: FileExplorerProps) => {
else return false else return false
} }
const getFocusedFolder = () => {
if (state.focusElement[0]) {
if (state.focusElement[0].type === 'folder' && state.focusElement[0].key) return state.focusElement[0].key
else if (state.focusElement[0].type === 'gist' && state.focusElement[0].key) return state.focusElement[0].key
else if (state.focusElement[0].type === 'file' && state.focusElement[0].key) return extractParentFromKey(state.focusElement[0].key) ? extractParentFromKey(state.focusElement[0].key) : name
else return name
}
}
const createNewFile = async (newFilePath: string) => { const createNewFile = async (newFilePath: string) => {
const fileManager = state.fileManager const fileManager = state.fileManager
@ -309,7 +332,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
// the files module. Please ask the user here if they want to overwrite // the files module. Please ask the user here if they want to overwrite
// a file and then just use `files.add`. The file explorer will // a file and then just use `files.add`. The file explorer will
// pick that up via the 'fileAdded' event from the files module. // pick that up via the 'fileAdded' event from the files module.
const parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key : extractParentFromKey(state.focusElement[0].key) : name const parentFolder = getFocusedFolder()
const expandPath = [...new Set([...state.expandPath, parentFolder])] const expandPath = [...new Set([...state.expandPath, parentFolder])]
setState(prevState => { setState(prevState => {
@ -355,11 +378,23 @@ export const FileExplorer = (props: FileExplorerProps) => {
}) })
} }
const publishToGist = () => { const publishToGist = (path?: string, type?: string) => {
modal('Create a public gist', `Are you sure you want to anonymously publish all your files in the ${name} workspace as a public gist on github.com?`, 'OK', toGist, 'Cancel', () => {}) modal('Create a public gist', `Are you sure you want to anonymously publish all your files in the ${name} workspace as a public gist on github.com?`, 'OK', () => toGist(path, type), 'Cancel', () => {})
}
const pushChangesToGist = (path?: string, type?: string) => {
modal('Create a public gist', 'Are you sure you want to push changes to remote gist file on github.com?', 'OK', () => toGist(path, type), 'Cancel', () => {})
} }
const toGist = (id?: string) => { const publishFolderToGist = (path?: string, type?: string) => {
modal('Create a public gist', `Are you sure you want to anonymously publish all your files in the ${path} folder as a public gist on github.com?`, 'OK', () => toGist(path, type), 'Cancel', () => {})
}
const publishFileToGist = (path?: string, type?: string) => {
modal('Create a public gist', `Are you sure you want to anonymously publish ${path} file as a public gist on github.com?`, 'OK', () => toGist(path, type), 'Cancel', () => {})
}
const toGist = (path?: string, type?: string) => {
const filesProvider = fileSystem.provider.provider const filesProvider = fileSystem.provider.provider
const proccedResult = function (error, data) { const proccedResult = function (error, data) {
if (error) { if (error) {
@ -393,7 +428,8 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
// If 'id' is not defined, it is not a gist update but a creation so we have to take the files from the browser explorer. // If 'id' is not defined, it is not a gist update but a creation so we have to take the files from the browser explorer.
const folder = id ? '/gists/' + id : '/' const folder = path || '/'
const id = type === 'gist' ? extractNameFromKey(path).split('-')[1] : null
packageFiles(filesProvider, folder, async (error, packaged) => { packageFiles(filesProvider, folder, async (error, packaged) => {
if (error) { if (error) {
@ -501,15 +537,15 @@ export const FileExplorer = (props: FileExplorerProps) => {
}) })
} }
const handleClickFile = (path: string) => { const handleClickFile = (path: string, type: string) => {
path = path.indexOf(props.name + '/') === 0 ? path.replace(props.name + '/', '') : path path = path.indexOf(props.name + '/') === 0 ? path.replace(props.name + '/', '') : path
state.fileManager.open(path) state.fileManager.open(path)
setState(prevState => { setState(prevState => {
return { ...prevState, focusElement: [{ key: path, type: 'file' }] } return { ...prevState, focusElement: [{ key: path, type }] }
}) })
} }
const handleClickFolder = async (path: string) => { const handleClickFolder = async (path: string, type: string) => {
if (state.ctrlKey) { if (state.ctrlKey) {
if (state.focusElement.findIndex(item => item.key === path) !== -1) { if (state.focusElement.findIndex(item => item.key === path) !== -1) {
setState(prevState => { setState(prevState => {
@ -517,7 +553,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
}) })
} else { } else {
setState(prevState => { setState(prevState => {
return { ...prevState, focusElement: [...prevState.focusElement, { key: path, type: 'folder' }] } return { ...prevState, focusElement: [...prevState.focusElement, { key: path, type }] }
}) })
} }
} else { } else {
@ -531,22 +567,22 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
setState(prevState => { setState(prevState => {
return { ...prevState, focusElement: [{ key: path, type: 'folder' }], expandPath } return { ...prevState, focusElement: [{ key: path, type }], expandPath }
}) })
} }
} }
const handleContextMenuFile = (pageX: number, pageY: number, path: string, content: string) => { const handleContextMenuFile = (pageX: number, pageY: number, path: string, content: string, type: string) => {
if (!content) return if (!content) return
setState(prevState => { setState(prevState => {
return { ...prevState, focusContext: { element: path, x: pageX, y: pageY, type: 'file' }, focusEdit: { ...prevState.focusEdit, lastEdit: content }, showContextMenu: prevState.focusEdit.element !== path } return { ...prevState, focusContext: { element: path, x: pageX, y: pageY, type }, focusEdit: { ...prevState.focusEdit, lastEdit: content }, showContextMenu: prevState.focusEdit.element !== path }
}) })
} }
const handleContextMenuFolder = (pageX: number, pageY: number, path: string, content: string) => { const handleContextMenuFolder = (pageX: number, pageY: number, path: string, content: string, type: string) => {
if (!content) return if (!content) return
setState(prevState => { setState(prevState => {
return { ...prevState, focusContext: { element: path, x: pageX, y: pageY, type: 'folder' }, focusEdit: { ...prevState.focusEdit, lastEdit: content }, showContextMenu: prevState.focusEdit.element !== path } return { ...prevState, focusContext: { element: path, x: pageX, y: pageY, type }, focusEdit: { ...prevState.focusEdit, lastEdit: content }, showContextMenu: prevState.focusEdit.element !== path }
}) })
} }
@ -618,7 +654,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
const handleNewFileInput = async (parentFolder?: string) => { const handleNewFileInput = async (parentFolder?: string) => {
if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key ? state.focusElement[0].key : name : extractParentFromKey(state.focusElement[0].key) ? extractParentFromKey(state.focusElement[0].key) : name : name if (!parentFolder) parentFolder = getFocusedFolder()
const expandPath = [...new Set([...state.expandPath, parentFolder])] const expandPath = [...new Set([...state.expandPath, parentFolder])]
await addInputField(fileSystem.provider.provider, 'file', parentFolder)(dispatch) await addInputField(fileSystem.provider.provider, 'file', parentFolder)(dispatch)
@ -629,7 +665,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
} }
const handleNewFolderInput = async (parentFolder?: string) => { const handleNewFolderInput = async (parentFolder?: string) => {
if (!parentFolder) parentFolder = state.focusElement[0] ? state.focusElement[0].type === 'folder' ? state.focusElement[0].key ? state.focusElement[0].key : name : extractParentFromKey(state.focusElement[0].key) ? extractParentFromKey(state.focusElement[0].key) : name : name if (!parentFolder) parentFolder = getFocusedFolder()
else if ((parentFolder.indexOf('.sol') !== -1) || (parentFolder.indexOf('.js') !== -1)) parentFolder = extractParentFromKey(parentFolder) else if ((parentFolder.indexOf('.sol') !== -1) || (parentFolder.indexOf('.js') !== -1)) parentFolder = extractParentFromKey(parentFolder)
const expandPath = [...new Set([...state.expandPath, parentFolder])] const expandPath = [...new Set([...state.expandPath, parentFolder])]
@ -705,12 +741,12 @@ export const FileExplorer = (props: FileExplorerProps) => {
label={label(file)} label={label(file)}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
if (state.focusEdit.element !== file.path) handleClickFolder(file.path) if (state.focusEdit.element !== file.path) handleClickFolder(file.path, file.type)
}} }}
onContextMenu={(e) => { onContextMenu={(e) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
handleContextMenuFolder(e.pageX, e.pageY, file.path, e.target.textContent) handleContextMenuFolder(e.pageX, e.pageY, file.path, e.target.textContent, file.type)
}} }}
labelClass={labelClass} labelClass={labelClass}
controlBehaviour={ state.ctrlKey } controlBehaviour={ state.ctrlKey }
@ -742,12 +778,12 @@ export const FileExplorer = (props: FileExplorerProps) => {
label={label(file)} label={label(file)}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
if (state.focusEdit.element !== file.path) handleClickFile(file.path) if (state.focusEdit.element !== file.path) handleClickFile(file.path, file.type)
}} }}
onContextMenu={(e) => { onContextMenu={(e) => {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
handleContextMenuFile(e.pageX, e.pageY, file.path, e.target.textContent) handleContextMenuFile(e.pageX, e.pageY, file.path, e.target.textContent, file.type)
}} }}
icon={icon} icon={icon}
labelClass={labelClass} labelClass={labelClass}
@ -841,6 +877,9 @@ export const FileExplorer = (props: FileExplorerProps) => {
e.stopPropagation() e.stopPropagation()
handleMouseOver(state.focusContext.element) handleMouseOver(state.focusContext.element)
}} }}
pushChangesToGist={pushChangesToGist}
publishFolderToGist={publishFolderToGist}
publishFileToGist={publishFileToGist}
/> />
} }
</div> </div>
@ -850,18 +889,41 @@ export const FileExplorer = (props: FileExplorerProps) => {
export default FileExplorer export default FileExplorer
async function packageFiles (filesProvider, directory, callback) { async function packageFiles (filesProvider, directory, callback) {
const isFile = filesProvider.isFile(directory)
const ret = {} const ret = {}
try {
await filesProvider.copyFolderToJson(directory, ({ path, content }) => { if (isFile) {
if (/^\s+$/.test(content) || !content.length) { try {
content = '// this line is added to create a gist. Empty file is not allowed.' filesProvider.get(directory, (error, content) => {
} if (error) throw new Error('An error ocurred while getting file content. ' + directory)
path = path.replace(/\//g, '...') if (/^\s+$/.test(content) || !content.length) {
ret[path] = { content } content = '// this line is added to create a gist. Empty file is not allowed.'
}) }
callback(null, ret) directory = directory.replace(/\//g, '...')
} catch (e) { ret[directory] = { content }
return callback(e) callback(null, ret)
})
} catch (e) {
return callback(e)
}
} else {
try {
await filesProvider.copyFolderToJson(directory, ({ path, content }) => {
if (/^\s+$/.test(content) || !content.length) {
content = '// this line is added to create a gist. Empty file is not allowed.'
}
if (path.indexOf('gist-') === 0) {
path = path.split('/')
path.shift()
path = path.join('/')
}
path = path.replace(/\//g, '...')
ret[path] = { content }
})
callback(null, ret)
} catch (e) {
return callback(e)
}
} }
} }

@ -258,7 +258,8 @@ const resolveDirectory = (root, path: string, files, content) => {
files = _.set(files, _path, { files = _.set(files, _path, {
isDirectory: true, isDirectory: true,
path, path,
name: extractNameFromKey(path), name: extractNameFromKey(path).indexOf('gist-') === 0 ? extractNameFromKey(path).split('-')[1] : extractNameFromKey(path),
type: extractNameFromKey(path).indexOf('gist-') === 0 ? 'gist' : 'folder',
child: { ...content[pathArr[pathArr.length - 1]], ...(prevFiles ? prevFiles.child : {}) } child: { ...content[pathArr[pathArr.length - 1]], ...(prevFiles ? prevFiles.child : {}) }
}) })
@ -278,7 +279,8 @@ const removePath = (root, path: string, pathName, files) => {
files = _.set(files, _path, { files = _.set(files, _path, {
isDirectory: true, isDirectory: true,
path, path,
name: extractNameFromKey(path), name: extractNameFromKey(path).indexOf('gist-') === 0 ? extractNameFromKey(path).split('-')[1] : extractNameFromKey(path),
type: extractNameFromKey(path).indexOf('gist-') === 0 ? 'gist' : 'folder',
child: prevFiles ? prevFiles.child : {} child: prevFiles ? prevFiles.child : {}
}) })
@ -336,7 +338,8 @@ const fileRenamed = (root, path: string, removePath: string, files, content) =>
files = _.set(files, _path, { files = _.set(files, _path, {
isDirectory: true, isDirectory: true,
path, path,
name: extractNameFromKey(path), name: extractNameFromKey(path).indexOf('gist-') === 0 ? extractNameFromKey(path).split('-')[1] : extractNameFromKey(path),
type: extractNameFromKey(path).indexOf('gist-') === 0 ? 'gist' : 'folder',
child: { ...content[pathArr[pathArr.length - 1]], ...prevFiles.child } child: { ...content[pathArr[pathArr.length - 1]], ...prevFiles.child }
}) })

@ -15,6 +15,7 @@ export interface File {
path: string, path: string,
name: string, name: string,
isDirectory: boolean, isDirectory: boolean,
type: string,
child?: File[] child?: File[]
} }
@ -24,7 +25,7 @@ export interface FileExplorerMenuProps {
fileManager: any, fileManager: any,
createNewFile: (folder?: string) => void, createNewFile: (folder?: string) => void,
createNewFolder: (parentFolder?: string) => void, createNewFolder: (parentFolder?: string) => void,
publishToGist: () => void, publishToGist: (path?: string) => void,
uploadFile: (target: EventTarget & HTMLInputElement) => void uploadFile: (target: EventTarget & HTMLInputElement) => void
} }
@ -35,7 +36,10 @@ export interface FileExplorerContextMenuProps {
deletePath: (path: string) => void, deletePath: (path: string) => void,
renamePath: (path: string, type: string) => void, renamePath: (path: string, type: string) => void,
hideContextMenu: () => void, hideContextMenu: () => void,
publishToGist?: () => void, publishToGist?: (path?: string, type?: string) => void,
pushChangesToGist?: (path?: string, type?: string) => void,
publishFolderToGist?: (path?: string, type?: string) => void,
publishFileToGist?: (path?: string, type?: string) => void,
runScript?: (path: string) => void, runScript?: (path: string) => void,
emit?: (id: string, path: string) => void, emit?: (id: string, path: string) => void,
pageX: number, pageX: number,

Loading…
Cancel
Save