diff --git a/src/app.js b/src/app.js index 02096d324c..ed24d0ef2b 100644 --- a/src/app.js +++ b/src/app.js @@ -17,6 +17,7 @@ var GistHandler = require('./lib/gist-handler') var helper = require('./lib/helper') var Storage = remixLib.Storage var Browserfiles = require('./app/files/browser-files') +var BrowserfilesTree = require('./app/files/browser-files-tree') var chromeCloudStorageSync = require('./app/files/chromeCloudStorageSync') var SharedFolder = require('./app/files/shared-folder') var Config = require('./config') @@ -111,11 +112,14 @@ class App { var self = this self._api = {} var fileStorage = new Storage('sol:') + var configStorage = new Storage('config:') self._api.config = new Config(fileStorage) executionContext.init(self._api.config) executionContext.listenOnLastBlock() self._api.filesProviders = {} self._api.filesProviders['browser'] = new Browserfiles(fileStorage) + self._api.filesProviders['config'] = new BrowserfilesTree('config', configStorage) + self._api.filesProviders['config'].init() var remixd = new Remixd() remixd.event.register('system', (message) => { if (message.error) toolTip(message.error) @@ -204,7 +208,7 @@ function run () { var self = this if (window.location.hostname === 'yann300.github.io') { - modalDialogCustom.alert(`This UNSTABLE ALPHA branch of Remix has been moved to http://ethereum.github.io/remix-live-alpha.`) + modalDialogCustom.alert('This UNSTABLE ALPHA branch of Remix has been moved to http://ethereum.github.io/remix-live-alpha.') } else if (window.location.hostname === 'ethereum.github.io' && window.location.pathname.indexOf('/remix-live-alpha') === 0) { modalDialogCustom.alert(`This instance of the Remix IDE is an UNSTABLE ALPHA branch.\n @@ -697,6 +701,17 @@ Please make a backup of your contracts and start using http://remix.ethereum.org }, newAccount: (pass, cb) => { udapp.newAccount(pass, cb) + }, + setConfig: (mod, path, content, cb) => { + self._api.filesProviders['config'].set(mod + '/' + path, content) + cb() + }, + getConfig: (mod, path, cb) => { + cb(null, self._api.filesProviders['config'].get(mod + '/' + path)) + }, + removeConfig: (mod, path, cb) => { + cb(null, self._api.filesProviders['config'].remove(mod + '/' + path)) + if (cb) cb() } } var rhpEvents = { diff --git a/src/app/files/browser-files-tree.js b/src/app/files/browser-files-tree.js new file mode 100644 index 0000000000..b9bde21c2d --- /dev/null +++ b/src/app/files/browser-files-tree.js @@ -0,0 +1,133 @@ +'use strict' + +var EventManager = require('remix-lib').EventManager + +function FilesTree (name, storage) { + var self = this + var event = new EventManager() + this.event = event + this.type = name + this.structFile = '.' + name + '.tree' + this.tree = {} + + this.exists = function (path, cb) { + cb(null, this._exists(path)) + } + + function updateRefs (path, type) { + var split = path.split('/') // this should be unprefixed path + var crawlpath = self.tree + var intermediatePath = '' + split.forEach((pathPart, index) => { + intermediatePath += pathPart + if (!crawlpath[pathPart]) crawlpath[intermediatePath] = {} + if (index < split.length - 1) { + crawlpath = crawlpath[intermediatePath] + intermediatePath += '/' + } else if (type === 'add') { + crawlpath[intermediatePath] = path + } else if (type === 'remove' && crawlpath[intermediatePath]) { + delete crawlpath[intermediatePath] + } + }) + storage.set(self.structFile, JSON.stringify(self.tree)) + } + + this._exists = function (path) { + var unprefixedpath = this.removePrefix(path) + return storage.exists(unprefixedpath) + } + + this.init = function (cb) { + var tree = storage.get(this.structFile) + this.tree = tree ? JSON.parse(tree) : {} + if (cb) cb() + } + + this.get = function (path, cb) { + var unprefixedpath = this.removePrefix(path) + var content = storage.get(unprefixedpath) + if (cb) { + cb(null, content) + } + return content + } + + this.set = function (path, content) { + var unprefixedpath = this.removePrefix(path) + updateRefs(unprefixedpath, 'add') + var exists = storage.exists(unprefixedpath) + if (!storage.set(unprefixedpath, content)) { + return false + } + if (!exists) { + event.trigger('fileAdded', [this.type + '/' + unprefixedpath, false]) + } else { + event.trigger('fileChanged', [this.type + '/' + unprefixedpath]) + } + return true + } + + this.addReadOnly = function (path, content) { + return this.set(path, content) + } + + this.isReadOnly = function (path) { + return false + } + + this.remove = function (path) { + var unprefixedpath = this.removePrefix(path) + updateRefs(unprefixedpath, 'remove') + if (!this._exists(unprefixedpath)) { + return false + } + if (!storage.remove(unprefixedpath)) { + return false + } + event.trigger('fileRemoved', [this.type + '/' + unprefixedpath]) + return true + } + + this.rename = function (oldPath, newPath, isFolder) { + var unprefixedoldPath = this.removePrefix(oldPath) + var unprefixednewPath = this.removePrefix(newPath) + updateRefs(unprefixedoldPath, 'remove') + updateRefs(unprefixednewPath, 'add') + if (storage.exists(unprefixedoldPath)) { + if (!storage.rename(unprefixedoldPath, unprefixednewPath)) { + return false + } + event.trigger('fileRenamed', [this.type + '/' + unprefixedoldPath, this.type + '/' + unprefixednewPath, isFolder]) + return true + } + return false + } + + this.resolveDirectory = function (path, callback) { + var self = this + if (path[0] === '/') path = path.substring(1) + if (!path) return callback(null, { [self.type]: { } }) + var tree = {} + path = self.removePrefix(path) + + var split = path.split('/') // this should be unprefixed path + var crawlpath = self.tree + split.forEach((pathPart, index) => { + if (crawlpath[pathPart]) crawlpath = crawlpath[pathPart] + }) + + for (var item in crawlpath) { + tree[item] = { isDirectory: typeof crawlpath[item] !== 'string' } + } + callback(null, tree) + } + + this.removePrefix = function (path) { + path = path.indexOf(this.type) === 0 ? path.replace(this.type, '') : path + if (path[0] === '/') return path.substring(1) + return path + } +} + +module.exports = FilesTree diff --git a/src/app/files/fileManager.js b/src/app/files/fileManager.js index 7614ed6779..ec044adb49 100644 --- a/src/app/files/fileManager.js +++ b/src/app/files/fileManager.js @@ -24,8 +24,10 @@ class FileManager { this.opt = opt this.opt.filesProviders['browser'].event.register('fileRenamed', (oldName, newName, isFolder) => { this.fileRenamedEvent(oldName, newName, isFolder) }) this.opt.filesProviders['localhost'].event.register('fileRenamed', (oldName, newName, isFolder) => { this.fileRenamedEvent(oldName, newName, isFolder) }) + this.opt.filesProviders['config'].event.register('fileRenamed', (oldName, newName, isFolder) => { this.fileRenamedEvent(oldName, newName, isFolder) }) this.opt.filesProviders['browser'].event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) }) this.opt.filesProviders['localhost'].event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) }) + this.opt.filesProviders['config'].event.register('fileRemoved', (path) => { this.fileRemovedEvent(path) }) // tabs var $filesEl = $('#files') diff --git a/src/app/panels/file-panel.js b/src/app/panels/file-panel.js index 98cae06722..b112a2af35 100644 --- a/src/app/panels/file-panel.js +++ b/src/app/panels/file-panel.js @@ -45,6 +45,7 @@ function filepanel (appAPI, filesProvider) { var swarmExplorer = new FileExplorer(appAPI, filesProvider['swarm']) var githubExplorer = new FileExplorer(appAPI, filesProvider['github']) var gistExplorer = new FileExplorer(appAPI, filesProvider['gist']) + var configExplorer = new FileExplorer(appAPI, filesProvider['config']) var dragbar = yo`
` @@ -91,6 +92,7 @@ function filepanel (appAPI, filesProvider) {