Merge pull request #1257 from ethereum/set-timeout

Queue file operation events
pull/1261/head^2
David Disu 4 years ago committed by GitHub
commit 50e46e43e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      apps/remix-ide-e2e/src/helpers/init.ts
  2. 4
      apps/remix-ide-e2e/src/tests/gist.spec.ts
  3. 2
      apps/remix-ide-e2e/src/tests/url.spec.ts
  4. 38
      apps/remix-ide/src/app/panels/file-panel.js
  5. 138
      libs/remix-ui/file-explorer/src/lib/actions/fileSystem.ts
  6. 2
      libs/remix-ui/file-explorer/src/lib/file-explorer.tsx

@ -2,18 +2,11 @@ import { NightwatchBrowser } from 'nightwatch'
require('dotenv').config() require('dotenv').config()
export default function (browser: NightwatchBrowser, callback: VoidFunction, url?: string, preloadPlugins = true, closeWorkspaceAlert = true): void { export default function (browser: NightwatchBrowser, callback: VoidFunction, url?: string, preloadPlugins = true): void {
browser browser
.url(url || 'http://127.0.0.1:8080') .url(url || 'http://127.0.0.1:8080')
.pause(5000) .pause(5000)
.switchBrowserTab(0) .switchBrowserTab(0)
.perform((done) => {
if (closeWorkspaceAlert) {
browser.waitForElementVisible('*[data-id="modalDialogModalBody"]', 60000)
.modalFooterOKClick()
}
done()
})
.fullscreenWindow(() => { .fullscreenWindow(() => {
if (preloadPlugins) { if (preloadPlugins) {
initModules(browser, () => { initModules(browser, () => {

@ -54,8 +54,8 @@ 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/gist-${gistid}"]`) .waitForElementVisible(`[data-id="treeViewLitreeViewItemgist-${gistid}"]`)
.click(`[data-id="treeViewLitreeViewItem/gist-${gistid}"]`) .click(`[data-id="treeViewLitreeViewItemgist-${gistid}"]`)
.openFile(`gist-${gistid}/README.txt`) .openFile(`gist-${gistid}/README.txt`)
} }
}) })

@ -10,7 +10,7 @@ const sources = [
module.exports = { module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0', true, false) init(browser, done, 'http://127.0.0.1:8080/#optimize=true&runs=300&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&code=cHJhZ21hIHNvbGlkaXR5ID49MC42LjAgPDAuNy4wOwoKaW1wb3J0ICJodHRwczovL2dpdGh1Yi5jb20vT3BlblplcHBlbGluL29wZW56ZXBwZWxpbi1jb250cmFjdHMvYmxvYi9tYXN0ZXIvY29udHJhY3RzL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBHZXRQYWlkIGlzIE93bmFibGUgewogIGZ1bmN0aW9uIHdpdGhkcmF3KCkgZXh0ZXJuYWwgb25seU93bmVyIHsKICB9Cn0', true)
}, },
'@sources': function () { '@sources': function () {

@ -166,12 +166,26 @@ module.exports = class Filepanel extends ViewPlugin {
return return
} }
// insert example contracts if there are no files to show // insert example contracts if there are no files to show
this._deps.fileProviders.browser.resolveDirectory('/', async (error, filesList) => { return new Promise((resolve, reject) => {
if (error) console.error(error) this._deps.fileProviders.browser.resolveDirectory('/', async (error, filesList) => {
if (Object.keys(filesList).length === 0) { if (error) return reject(error)
await this.createWorkspace('default_workspace') if (Object.keys(filesList).length === 0) {
} await this.createWorkspace('default_workspace')
this.getWorkspaces() resolve('default_workspace')
} else {
this._deps.fileProviders.browser.resolveDirectory('.workspaces', async (error, filesList) => {
if (error) return reject(error)
if (Object.keys(filesList).length > 0) {
const workspacePath = Object.keys(filesList)[0].split('/').filter(val => val)
const workspaceName = workspacePath[workspacePath.length - 1]
this._deps.fileProviders.workspace.setWorkspace(workspaceName)
return resolve(workspaceName)
}
return reject(new Error('Can\'t find available workspace.'))
})
}
})
}) })
} }
@ -213,13 +227,11 @@ module.exports = class Filepanel extends ViewPlugin {
await this.request.setWorkspace(workspaceName) // tells the react component to switch to that workspace await this.request.setWorkspace(workspaceName) // tells the react component to switch to that workspace
if (setDefaults) { if (setDefaults) {
for (const file in examples) { for (const file in examples) {
setTimeout(async () => { // space creation of files to give react ui time to update. try {
try { await workspaceProvider.set(examples[file].name, examples[file].content)
await workspaceProvider.set(examples[file].name, examples[file].content) } catch (error) {
} catch (error) { console.error(error)
console.error(error) }
}
}, 10)
} }
} }
} }

@ -2,6 +2,12 @@ import React from 'react'
import { File } from '../types' import { File } from '../types'
import { extractNameFromKey, extractParentFromKey } from '../utils' import { extractNameFromKey, extractParentFromKey } from '../utils'
const queuedEvents = []
const pendingEvents = {}
let provider = null
let plugin = null
let dispatch: React.Dispatch<any> = null
export const fetchDirectoryError = (error: any) => { export const fetchDirectoryError = (error: any) => {
return { return {
type: 'FETCH_DIRECTORY_ERROR', type: 'FETCH_DIRECTORY_ERROR',
@ -183,35 +189,25 @@ export const fileRenamedSuccess = (path: string, removePath: string, files) => {
} }
} }
export const init = (provider, workspaceName: string, plugin, registry) => (dispatch: React.Dispatch<any>) => { export const init = (fileProvider, filePanel, registry) => (reducerDispatch: React.Dispatch<any>) => {
provider = fileProvider
plugin = filePanel
dispatch = reducerDispatch
if (provider) { if (provider) {
provider.event.on('fileAdded', async (filePath) => { provider.event.on('fileAdded', async (filePath) => {
if (extractParentFromKey(filePath) === '/.workspaces') return await executeEvent('fileAdded', filePath)
const path = extractParentFromKey(filePath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
dispatch(fileAddedSuccess(path, data))
if (filePath.includes('_test.sol')) {
plugin.emit('newTestFileCreated', filePath)
}
}) })
provider.event.on('folderAdded', async (folderPath) => { provider.event.on('folderAdded', async (folderPath) => {
if (extractParentFromKey(folderPath) === '/.workspaces') return await executeEvent('folderAdded', folderPath)
const path = extractParentFromKey(folderPath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
dispatch(folderAddedSuccess(path, data))
}) })
provider.event.on('fileRemoved', async (removePath) => { provider.event.on('fileRemoved', async (removePath) => {
const path = extractParentFromKey(removePath) || provider.workspace || provider.type || '' await executeEvent('fileRemoved', removePath)
dispatch(fileRemovedSuccess(path, removePath))
}) })
provider.event.on('fileRenamed', async (oldPath) => { provider.event.on('fileRenamed', async (oldPath) => {
const path = extractParentFromKey(oldPath) || provider.workspace || provider.type || '' await executeEvent('fileRenamed', oldPath)
const data = await fetchDirectoryContent(provider, path) })
provider.event.on('rootFolderChanged', async () => {
dispatch(fileRenamedSuccess(path, oldPath, data)) await executeEvent('rootFolderChanged')
}) })
provider.event.on('fileExternallyChanged', async (path: string, file: { content: string }) => { provider.event.on('fileExternallyChanged', async (path: string, file: { content: string }) => {
const config = registry.get('config').api const config = registry.get('config').api
@ -232,10 +228,6 @@ export const init = (provider, workspaceName: string, plugin, registry) => (disp
provider.event.on('fileRenamedError', async () => { provider.event.on('fileRenamedError', async () => {
dispatch(displayNotification('File Renamed Failed', '', 'Ok', 'Cancel')) dispatch(displayNotification('File Renamed Failed', '', 'Ok', 'Cancel'))
}) })
provider.event.on('rootFolderChanged', async () => {
workspaceName = provider.workspace || provider.type || ''
fetchDirectory(provider, workspaceName)(dispatch)
})
dispatch(fetchProviderSuccess(provider)) dispatch(fetchProviderSuccess(provider))
} else { } else {
dispatch(fetchProviderError('No provider available')) dispatch(fetchProviderError('No provider available'))
@ -294,3 +286,99 @@ export const hideNotification = () => {
export const closeNotificationModal = () => (dispatch: React.Dispatch<any>) => { export const closeNotificationModal = () => (dispatch: React.Dispatch<any>) => {
dispatch(hideNotification()) dispatch(hideNotification())
} }
const fileAdded = async (filePath: string) => {
if (extractParentFromKey(filePath) === '/.workspaces') return
const path = extractParentFromKey(filePath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
await dispatch(fileAddedSuccess(path, data))
if (filePath.includes('_test.sol')) {
plugin.emit('newTestFileCreated', filePath)
}
}
const folderAdded = async (folderPath: string) => {
if (extractParentFromKey(folderPath) === '/.workspaces') return
const path = extractParentFromKey(folderPath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
await dispatch(folderAddedSuccess(path, data))
}
const fileRemoved = async (removePath: string) => {
const path = extractParentFromKey(removePath) || provider.workspace || provider.type || ''
await dispatch(fileRemovedSuccess(path, removePath))
}
const fileRenamed = async (oldPath: string) => {
const path = extractParentFromKey(oldPath) || provider.workspace || provider.type || ''
const data = await fetchDirectoryContent(provider, path)
await dispatch(fileRenamedSuccess(path, oldPath, data))
}
const rootFolderChanged = async () => {
const workspaceName = provider.workspace || provider.type || ''
await fetchDirectory(provider, workspaceName)(dispatch)
}
const executeEvent = async (eventName: 'fileAdded' | 'folderAdded' | 'fileRemoved' | 'fileRenamed' | 'rootFolderChanged', path?: string) => {
if (Object.keys(pendingEvents).length) {
return queuedEvents.push({ eventName, path })
}
pendingEvents[eventName + path] = { eventName, path }
switch (eventName) {
case 'fileAdded':
await fileAdded(path)
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
case 'folderAdded':
await folderAdded(path)
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
case 'fileRemoved':
await fileRemoved(path)
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
case 'fileRenamed':
await fileRenamed(path)
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
case 'rootFolderChanged':
await rootFolderChanged()
delete pendingEvents[eventName + path]
if (queuedEvents.length) {
const next = queuedEvents.pop()
await executeEvent(next.eventName, next.path)
}
break
}
}

@ -126,7 +126,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
const editRef = useRef(null) const editRef = useRef(null)
useEffect(() => { useEffect(() => {
init(props.filesProvider, props.name, props.plugin, props.registry)(dispatch) init(props.filesProvider, props.plugin, props.registry)(dispatch)
}, []) }, [])
useEffect(() => { useEffect(() => {

Loading…
Cancel
Save