Unverified Commit 134245e0 authored by yann300's avatar yann300 Committed by GitHub

Merge pull request #1016 from ethereum/file-exlorer

Fix file explorer update events
parents f9e518ac 0b394f74
......@@ -2,7 +2,7 @@ language: node_js
node_js:
- "7"
script:
- npm run lint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run build
- npm run lint && npm run test && npm run downloadsolc && npm run make-mock-compiler && npm run setupremix && npm run build
- ./ci/browser_tests.sh
deploy:
- provider: script
......
......@@ -4,14 +4,7 @@ set -e
setupRemixd () {
mkdir remixdSharedfolder
cd remixdSharedfolder
echo "contract test1 { function get () returns (uint) { return 8; }}" > contract1.sol
echo "contract test2 { function get () returns (uint) { return 9; }}" > contract2.sol
mkdir folder1
cd folder1
echo "contract test1 { function get () returns (uint) { return 10; }}" > contract1.sol
echo "contract test2 { function get () returns (uint) { return 11; }}" > contract2.sol
cd ..
cd contracts
echo 'sharing folder: '
echo $PWD
node ../node_modules/remixd/src/main.js -s $PWD &
......
contract test1 { function get () returns (uint) { return 8; }}
\ No newline at end of file
contract test2 { function get () returns (uint) { return 9; }}
\ No newline at end of file
contract test1 { function get () returns (uint) { return 10; }}
\ No newline at end of file
contract test2 { function get () returns (uint) { return 11; }}
\ No newline at end of file
contract test2 { function get () returns (uint) { return 11; }}
\ No newline at end of file
contract test2 { function get () returns (uint) { return 11; }}
\ No newline at end of file
......@@ -139,7 +139,8 @@
]
},
"scripts": {
"pullremix": "mkdir remix; git clone https://github.com/ethereum/remix; cd ..",
"setupremix": "npm run pullremix && npm run linkremixcore && npm run linkremixlib && npm run linkremixsolidity && npm run linkremixdebugger;",
"pullremix": "git clone https://github.com/ethereum/remix",
"linkremixcore": "cd node_modules && rm -rf remix-core && ln -s ../remix/remix-core remix-core && cd ..",
"linkremixlib": "cd node_modules && rm -rf remix-lib && ln -s ../remix/remix-lib remix-lib && cd ..",
"linkremixsolidity": "cd node_modules && rm -rf remix-solidity && ln -s ../remix/remix-solidity remix-solidity && cd ..",
......
......@@ -497,10 +497,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
switchFile: function (path) {
fileManager.switchFile(path)
},
event: this.event,
currentFile: function () {
return config.get('currentFile')
},
event: fileManager.event,
config: config,
currentContent: function () {
return editor.get(config.get('currentFile'))
},
......
......@@ -5,7 +5,9 @@ class BasicReadOnlyExplorer {
constructor (type) {
this.event = new EventManager()
this.files = {}
this.paths = {}
this.normalizedNames = {} // contains the raw url associated with the displayed path
this.paths[type] = {}
this.type = type
this.readonly = true
}
......@@ -36,19 +38,32 @@ class BasicReadOnlyExplorer {
}
set (path, content, cb) {
this.addReadOnly(path, content)
var unprefixedPath = this.removePrefix(path)
this.addReadOnly(unprefixedPath, content)
if (cb) cb()
return true
}
addReadOnly (path, content, rawPath) {
var unprefixedPath = this.removePrefix(path)
try { // lazy try to format JSON
content = JSON.stringify(JSON.parse(content), null, '\t')
} catch (e) {}
this.files[this.type + '/' + unprefixedPath] = content
// splitting off the path in a tree structure, the json tree is used in `resolveDirectory`
var split = path
var folder = false
while (split.lastIndexOf('/') !== -1) {
var subitem = split.substring(split.lastIndexOf('/'))
split = split.substring(0, split.lastIndexOf('/'))
if (!this.paths[this.type + '/' + split]) {
this.paths[this.type + '/' + split] = {}
}
this.paths[this.type + '/' + split][split + subitem] = { isDirectory: folder }
folder = true
}
this.paths[this.type][split] = { isDirectory: folder }
this.files[path] = content
this.normalizedNames[rawPath] = path
this.event.trigger('fileAdded', [this.type + '/' + unprefixedPath, true])
this.event.trigger('fileAdded', [path, true])
return true
}
......@@ -68,46 +83,12 @@ class BasicReadOnlyExplorer {
return this.files
}
//
// Tree model for files
// {
// 'a': { }, // empty directory 'a'
// 'b': {
// 'c': {}, // empty directory 'b/c'
// 'd': { '/readonly': true, '/content': 'Hello World' } // files 'b/c/d'
// 'e': { '/readonly': false, '/path': 'b/c/d' } // symlink to 'b/c/d'
// 'f': { '/readonly': false, '/content': '<executable>', '/mode': 0755 }
// }
// }
//
resolveDirectory (path, callback /* (error, filesList) => { } */) {
resolveDirectory (path, callback) {
var self = this
if (path[0] === '/') path = path.substring(1)
if (!path) return callback(null, { [self.type]: { } })
var tree = {}
// This does not include '.remix.config', because it is filtered
// inside list().
Object.keys(this.list()).forEach(function (path) {
hashmapize(tree, path, {
'/readonly': self.isReadOnly(path),
'/content': self.get(path)
})
})
return callback(null, tree[path] || {})
function hashmapize (obj, path, val) {
var nodes = path.split('/')
var i = 0
for (; i < nodes.length - 1; i++) {
var node = nodes[i]
if (obj[node] === undefined) {
obj[node] = {}
}
obj = obj[node]
}
obj[nodes[i]] = val
}
// we just return the json tree populated by `addReadOnly`
callback(null, this.paths[path])
}
removePrefix (path) {
......
......@@ -103,55 +103,29 @@ function Files (storage) {
return false
}
//
// Tree model for files
// {
// 'a': { }, // empty directory 'a'
// 'b': {
// 'c': {}, // empty directory 'b/c'
// 'd': { '/readonly': true, '/content': 'Hello World' } // files 'b/c/d'
// 'e': { '/readonly': false, '/path': 'b/c/d' } // symlink to 'b/c/d'
// 'f': { '/readonly': false, '/content': '<executable>', '/mode': 0755 }
// }
// }
//
this.resolveDirectory = function (path, callback) {
var self = this
if (path[0] === '/') path = path.substring(1)
if (!path) return callback(null, { [self.type]: { } })
path = self.removePrefix(path)
var filesList = {}
var tree = {}
// add r/w filesList to the list
storage.keys().forEach((path) => {
// NOTE: as a temporary measure do not show the config file
if (path !== '.remix.config') {
filesList[self.type + '/' + path] = false
filesList[path] = false
}
})
// add r/o files to the list
Object.keys(readonly).forEach((path) => {
filesList[self.type + '/' + path] = true
filesList[path] = true
})
Object.keys(filesList).forEach(function (path) {
hashmapize(tree, path, {
'/readonly': self.isReadOnly(path),
'/content': self.get(path)
tree[path] = { isDirectory: false }
})
})
return callback(null, tree[path] || {})
function hashmapize (obj, path, val) {
var nodes = path.split('/')
var i = 0
for (; i < nodes.length - 1; i++) {
var node = nodes[i]
if (obj[node] === undefined) {
obj[node] = {}
}
obj = obj[node]
}
obj[nodes[i]] = val
}
return callback(null, tree)
}
this.removePrefix = function (path) {
......
This diff is collapsed.
......@@ -47,6 +47,7 @@ class FileManager {
self.switchFile(Object.keys(self.tabbedFiles)[0])
} else {
opt.editor.displayEmptyReadOnlySession()
self.opt.config.set('currentFile', '')
}
return false
})
......@@ -98,7 +99,6 @@ class FileManager {
// Display files that have already been selected
refreshTabs (newfile) {
var self = this
if (newfile) {
this.tabbedFiles[newfile] = newfile
}
......@@ -109,29 +109,32 @@ class FileManager {
for (var file in this.tabbedFiles) {
$filesEl.append(yo`<li class="file"><span class="name">${file}</span><span class="remove"><i class="fa fa-close"></i></span></li>`)
}
var currentFileOpen = !!this.opt.config.get('currentFile')
if (currentFileOpen) {
var active = $('#files .file').filter(function () { return $(this).find('.name').text() === self.opt.config.get('currentFile') })
active.addClass('active')
}
$('#input').toggle(currentFileOpen)
$('#output').toggle(currentFileOpen)
var active = $('#files .file').filter(function () {
return $(this).find('.name').text() === newfile
})
if (active.length) active.addClass('active')
else this.switchFile()
// $('#input').toggle(active)
$('#output').toggle(active)
}
switchFile (file) {
var self = this
if (!file) {
self.opt.filesProviders['browser'].resolveDirectory('/', (error, filesTree) => {
if (file) return _switchFile(file)
else {
var browserProvider = self.opt.filesProviders['browser']
browserProvider.resolveDirectory('browser', (error, filesTree) => {
if (error) console.error(error)
var fileList = Object.keys(flatten(filesTree))
var fileList = Object.keys(filesTree)
if (fileList.length) {
file = fileList[0]
if (file) _switchFile(file)
_switchFile(browserProvider.type + '/' + fileList[0])
} else {
self.event.trigger('currentFileChanged', [])
}
})
} else _switchFile(file)
function _switchFile () {
}
function _switchFile (file) {
self.saveCurrentFile()
self.opt.config.set('currentFile', file)
self.refreshTabs(file)
......@@ -179,23 +182,3 @@ class FileManager {
}
module.exports = FileManager
function flatten (tree) {
var flat = {}
var names = Object.keys(tree || {})
if (!names.length) return
else {
names.forEach(name => {
if ('/content' in tree[name]) flat[name] = false
else {
var subflat = flatten(tree[name])
if (!subflat) {
// empty folder
} else {
Object.keys(subflat).forEach(path => { flat[name + '/' + path] = false })
}
}
})
return flat
}
}
......@@ -137,19 +137,6 @@ module.exports = class SharedFolder {
return true
}
//
// Tree model for files
// {
// 'a': { }, // empty directory 'a'
// 'b': {
// 'c': {}, // empty directory 'b/c'
// 'd': { '/readonly': true, '/content': 'Hello World' } // files 'b/c/d'
// 'e': { '/readonly': false, '/path': 'b/c/d' } // symlink to 'b/c/d'
// 'f': { '/readonly': false, '/content': '<executable>', '/mode': 0755 }
// }
// }
//
removePrefix (path) {
path = path.indexOf(this.type) === 0 ? path.replace(this.type, '') : path
if (path[0] === '/') return path.substring(1)
......@@ -160,7 +147,7 @@ module.exports = class SharedFolder {
var self = this
if (path[0] === '/') path = path.substring(1)
if (!path) return callback(null, { [self.type]: { } })
path = self.removePrefix('' + (path || ''))
path = self.removePrefix(path)
self.remixd.dir(path, callback)
}
}
......
/* global FileReader */
var async = require('async')
var $ = require('jquery')
var yo = require('yo-yo')
......@@ -73,7 +74,7 @@ function filepanel (appAPI, filesProvider) {
</div>
<div class=${css.treeviews}>
<div class=${css.treeview}>${fileExplorer.init()}</div>
<div class="filesystemexplorer ${css.treeview}"></div>
<div class="filesystemexplorer ${css.treeview}">${fileSystemExplorer.init()}</div>
<div class="swarmexplorer ${css.treeview}">${swarmExplorer.init()}</div>
<div class="githubexplorer ${css.treeview}">${githubExplorer.init()}</div>
<div class="gistexplorer ${css.treeview}">${gistExplorer.init()}</div>
......@@ -87,7 +88,7 @@ function filepanel (appAPI, filesProvider) {
var event = new EventManager()
self.event = event
var element = template()
fileExplorer.ensureRoot()
var containerFileSystem = element.querySelector('.filesystemexplorer')
var websocketconn = element.querySelector('.websocketconn')
filesProvider['localhost'].remixd.event.register('connecting', (event) => {
......@@ -143,7 +144,30 @@ function filepanel (appAPI, filesProvider) {
// 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
// pick that up via the 'fileAdded' event from the files module.
;[...this.files].forEach(fileExplorer.api.addFile)
;[...this.files].forEach((file) => {
var files = fileExplorer.files
function loadFile () {
var fileReader = new FileReader()
fileReader.onload = function (event) {
if (helper.checkSpecialChars(file.name)) {
modalDialogCustom.alert('Special characters are not allowed')
return
}
var success = files.set(name, event.target.result)
if (!success) modalDialogCustom.alert('Failed to create file ' + name)
else self.events.trigger('focus', [name])
}
fileReader.readAsText(file)
}
var name = files.type + '/' + file.name
if (!files.exists(name)) {
loadFile()
} else {
modalDialogCustom.confirm(null, `The file ${name} already exists! Would you like to overwrite it?`, () => { loadFile() })
}
})
}
// ----------------- resizeable ui ---------------
......@@ -200,7 +224,6 @@ function filepanel (appAPI, filesProvider) {
* @param {String} txHash - hash of the transaction
*/
function connectToLocalhost () {
var container = document.querySelector('.filesystemexplorer')
if (filesProvider['localhost'].isConnected()) {
filesProvider['localhost'].close((error) => {
if (error) console.log(error)
......@@ -213,10 +236,7 @@ function filepanel (appAPI, filesProvider) {
if (error) {
console.log(error)
} else {
if (fileSystemExplorer.element && container.children.length > 0) {
container.removeChild(fileSystemExplorer.element)
}
container.appendChild(fileSystemExplorer.init())
fileSystemExplorer.ensureRoot()
}
})
}})
......
......@@ -77,7 +77,7 @@ var css = csjs`
}
.dragbar {
position : absolute;
top : 37px;
top : 29px;
width : 0.5em;
right : 0;
bottom : 0;
......
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