From 59b683aa7b5bdcc32278cb7a6a299e1994cd3dad Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 09:31:51 +0100 Subject: [PATCH 01/11] listen on plugin msg --- src/pluginManager.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pluginManager.js b/src/pluginManager.js index 2c8d4393dd..56cdd29cd2 100644 --- a/src/pluginManager.js +++ b/src/pluginManager.js @@ -46,6 +46,11 @@ class PluginManager { })) } }) + + window.addEventListener('message', (event) => { + if (event.type === 'message' && this.inFocus === event.origin) { + } + }, false) } register (desc, content) { this.plugins[desc.title] = {content, origin: desc.url} From 03fafd239b0ea1a8f519cbb6c2fd16e5cc217fe0 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 13:22:14 +0100 Subject: [PATCH 02/11] add browser file tree --- src/app/files/browser-files-tree.js | 130 ++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/app/files/browser-files-tree.js diff --git a/src/app/files/browser-files-tree.js b/src/app/files/browser-files-tree.js new file mode 100644 index 0000000000..e04850602d --- /dev/null +++ b/src/app/files/browser-files-tree.js @@ -0,0 +1,130 @@ +'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 + split.forEach((pathPart, index) => { + if (!crawlpath[pathPart]) crawlpath[pathPart] = {} + if (index < split.length - 1) { + crawlpath = crawlpath[pathPart] + } else if (type === 'add') { + crawlpath[pathPart] = path + } else if (type === 'remove' && crawlpath[pathPart]) { + delete crawlpath[pathPart] + } + }) + 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 From eb5e07ec21223a11bcb99fdfd1b72fe2df0c8920 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 13:23:49 +0100 Subject: [PATCH 03/11] add config explorer --- src/app.js | 4 ++++ src/app/files/fileManager.js | 2 ++ src/app/panels/file-panel.js | 7 +++++++ src/config.js | 1 + 4 files changed, 14 insertions(+) diff --git a/src/app.js b/src/app.js index 02096d324c..948197ff06 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) 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) {
${fileExplorer.init()}
+
${configExplorer.init()}
${fileSystemExplorer.init()}
${swarmExplorer.init()}
${githubExplorer.init()}
@@ -106,6 +108,7 @@ function filepanel (appAPI, filesProvider) { self.event = event var element = template() fileExplorer.ensureRoot() + configExplorer.ensureRoot() var websocketconn = element.querySelector('.websocketconn') filesProvider['localhost'].remixd.event.register('connecting', (event) => { websocketconn.style.color = styles.colors.yellow @@ -134,6 +137,10 @@ function filepanel (appAPI, filesProvider) { appAPI.switchFile(path) }) + configExplorer.events.register('focus', function (path) { + appAPI.switchFile(path) + }) + fileSystemExplorer.events.register('focus', function (path) { appAPI.switchFile(path) }) diff --git a/src/config.js b/src/config.js index 49c349ec3f..5339159cbf 100644 --- a/src/config.js +++ b/src/config.js @@ -35,6 +35,7 @@ function Config (storage) { this.ensureStorageUpdated = function (key) { if (key === 'currentFile') { if (this.items[key] && this.items[key] !== '' && + this.items[key].indexOf('config/') !== 0 && this.items[key].indexOf('browser/') !== 0 && this.items[key].indexOf('localhost/') !== 0 && this.items[key].indexOf('swarm/') !== 0 && From c418d3e6616c24cf528aed7ff89adfd0b4904f79 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 13:25:26 +0100 Subject: [PATCH 04/11] add api or config explorer --- src/app.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/app.js b/src/app.js index 948197ff06..173990a012 100644 --- a/src/app.js +++ b/src/app.js @@ -701,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 = { From c9f70f4a45d8012ece7255f507c91e879fcad440 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 13:26:06 +0100 Subject: [PATCH 05/11] listen on request intergration --- src/pluginManager.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/pluginManager.js b/src/pluginManager.js index 56cdd29cd2..9efd34362a 100644 --- a/src/pluginManager.js +++ b/src/pluginManager.js @@ -48,7 +48,23 @@ class PluginManager { }) window.addEventListener('message', (event) => { - if (event.type === 'message' && this.inFocus === event.origin) { + function response (type, callid, error, result) { + self.post(self.inFocus, JSON.stringify({ + id: callid, + type: type, + error: error, + result: result + })) + } + if (event.type === 'message' && this.inFocus && this.plugins[this.inFocus] && this.plugins[this.inFocus].origin === event.origin) { + var data = JSON.parse(event.data) + data.arguments.unshift(this.inFocus) + if (allowedapi[data.type]) { + data.arguments.push((error, result) => { + response(data.type, data.id, error, result) + }) + api[data.type].apply({}, data.arguments) + } } }, false) } From 32e354ef3f12f5e0e49904c55a00317f575a9ab4 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 13:26:21 +0100 Subject: [PATCH 06/11] comments --- src/pluginManager.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/pluginManager.js b/src/pluginManager.js index 9efd34362a..fd263b31d6 100644 --- a/src/pluginManager.js +++ b/src/pluginManager.js @@ -7,12 +7,35 @@ * - compilationData (that is triggered just after a focus - and send the current compilation data or null) * - compilationFinished (that is only sent to the plugin that has focus) * - * @param {String} txHash - hash of the transaction + * Plugin can emit messages and receive response. + * + * CONFIG: + * - getConfig(filename). The data to send should be formatted like: + * { + * type: 'getConfig', + * arguments: ['filename.ext'], + * id: + * } + * the plugin will reveice a response like: + * { + * type: 'getConfig', + * id: + * error, + * result + * } + * same apply for the other call + * - setConfig(filename, content) + * - removeConfig + * + * See index.html and remix.js in test-browser folder for sample + * */ class PluginManager { constructor (api, events) { + var self = this this.plugins = {} this.inFocus + var allowedapi = {'setConfig': 1, 'getConfig': 1, 'removeConfig': 1} events.compiler.register('compilationFinished', (success, data, source) => { if (this.inFocus) { // trigger to the current focus From ef50e98c25dcae9e595d8be1641f844776ebe45f Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 13:26:36 +0100 Subject: [PATCH 07/11] fix normalize path --- src/app/files/file-explorer.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/files/file-explorer.js b/src/app/files/file-explorer.js index 82ec08c670..fb9f468f24 100644 --- a/src/app/files/file-explorer.js +++ b/src/app/files/file-explorer.js @@ -173,10 +173,9 @@ function fileExplorer (appAPI, files) { }) function normalize (path, filesList) { - var prefix = path.split('/')[0] var newList = {} Object.keys(filesList).forEach(key => { - newList[prefix + '/' + key] = filesList[key].isDirectory ? {} : { '/content': true } + newList[path + '/' + key] = filesList[key].isDirectory ? {} : { '/content': true } }) return newList } From 7141780e89df33520bc058426bf54a51da020c15 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 13:26:47 +0100 Subject: [PATCH 08/11] add sample --- test-browser/plugin/index.html | 46 ++++++++++++++++++++++++++++++++++ test-browser/plugin/remix.js | 35 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 test-browser/plugin/index.html create mode 100644 test-browser/plugin/remix.js diff --git a/test-browser/plugin/index.html b/test-browser/plugin/index.html new file mode 100644 index 0000000000..2cb1662902 --- /dev/null +++ b/test-browser/plugin/index.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + +
PLUGIN
+ +
+ add config
+ remove config
+ get config
+
+
+ + diff --git a/test-browser/plugin/remix.js b/test-browser/plugin/remix.js new file mode 100644 index 0000000000..976cb1ae6f --- /dev/null +++ b/test-browser/plugin/remix.js @@ -0,0 +1,35 @@ + + +function receiveMessage (event) { + console.log('receiveMessage', event.data, event.source, event.origin) + document.getElementById('compilationdata').innerHTML += event.data + '
' +} +window.addEventListener('message', receiveMessage, false) + +window.onload = function () { + document.querySelector('input#testmessageadd').addEventListener('click', function () { + window.parent.postMessage(JSON.stringify({ + type: 'setConfig', + arguments: [document.getElementById('filename').value, document.getElementById('valuetosend').value], + id: 34 + }), 'http://127.0.0.1:8080') + }) + + document.querySelector('input#testmessageremove').addEventListener('click', function () { + window.parent.postMessage(JSON.stringify({ + type: 'removeConfig', + arguments: [document.getElementById('filename').value], + id: 35 + }), 'http://127.0.0.1:8080') + }) + + document.querySelector('input#testmessagerget').addEventListener('click', function () { + window.parent.postMessage(JSON.stringify({ + type: 'getConfig', + arguments: [document.getElementById('filename').value], + id: 36 + }), 'http://127.0.0.1:8080') + }) +} + + From 6fc8f63c8f1308303114a9c87fb285c523107b0a Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 13:27:25 +0100 Subject: [PATCH 09/11] standard --- src/app.js | 2 +- test-browser/plugin/remix.js | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/app.js b/src/app.js index 173990a012..ed24d0ef2b 100644 --- a/src/app.js +++ b/src/app.js @@ -208,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 diff --git a/test-browser/plugin/remix.js b/test-browser/plugin/remix.js index 976cb1ae6f..5449df96f1 100644 --- a/test-browser/plugin/remix.js +++ b/test-browser/plugin/remix.js @@ -1,5 +1,4 @@ - function receiveMessage (event) { console.log('receiveMessage', event.data, event.source, event.origin) document.getElementById('compilationdata').innerHTML += event.data + '
' @@ -31,5 +30,3 @@ window.onload = function () { }), 'http://127.0.0.1:8080') }) } - - From b378283873e70cf52a94be6fb37b5f62aa69148b Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 21:46:30 +0100 Subject: [PATCH 10/11] fix test --- test-browser/tests/sharedFolderExplorer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test-browser/tests/sharedFolderExplorer.js b/test-browser/tests/sharedFolderExplorer.js index 9eb553dd1e..711359d59c 100644 --- a/test-browser/tests/sharedFolderExplorer.js +++ b/test-browser/tests/sharedFolderExplorer.js @@ -71,6 +71,7 @@ function runTests (browser, testData) { .waitForElementVisible('[data-path="localhost/contract1.sol"]') .assert.containsText('[data-path="localhost/contract1.sol"]', 'contract1.sol') .assert.containsText('[data-path="localhost/contract2.sol"]', 'contract2.sol') + .waitForElementVisible('[data-path="localhost/folder1/contract1.sol"]') .assert.containsText('[data-path="localhost/folder1/contract1.sol"]', 'contract1.sol') .assert.containsText('[data-path="localhost/folder1/contract2.sol"]', 'contract2.sol') // load and test sub folder .click('[data-path="localhost/folder1/contract2.sol"]') From bc11663d76fcec7930ea40c37f9c0e9e3a09bc78 Mon Sep 17 00:00:00 2001 From: yann300 Date: Tue, 27 Feb 2018 22:36:50 +0100 Subject: [PATCH 11/11] fix file normalization --- src/app/files/browser-files-tree.js | 13 ++++++++----- src/app/files/file-explorer.js | 3 ++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/app/files/browser-files-tree.js b/src/app/files/browser-files-tree.js index e04850602d..b9bde21c2d 100644 --- a/src/app/files/browser-files-tree.js +++ b/src/app/files/browser-files-tree.js @@ -17,14 +17,17 @@ function FilesTree (name, storage) { function updateRefs (path, type) { var split = path.split('/') // this should be unprefixed path var crawlpath = self.tree + var intermediatePath = '' split.forEach((pathPart, index) => { - if (!crawlpath[pathPart]) crawlpath[pathPart] = {} + intermediatePath += pathPart + if (!crawlpath[pathPart]) crawlpath[intermediatePath] = {} if (index < split.length - 1) { - crawlpath = crawlpath[pathPart] + crawlpath = crawlpath[intermediatePath] + intermediatePath += '/' } else if (type === 'add') { - crawlpath[pathPart] = path - } else if (type === 'remove' && crawlpath[pathPart]) { - delete crawlpath[pathPart] + crawlpath[intermediatePath] = path + } else if (type === 'remove' && crawlpath[intermediatePath]) { + delete crawlpath[intermediatePath] } }) storage.set(self.structFile, JSON.stringify(self.tree)) diff --git a/src/app/files/file-explorer.js b/src/app/files/file-explorer.js index fb9f468f24..82ec08c670 100644 --- a/src/app/files/file-explorer.js +++ b/src/app/files/file-explorer.js @@ -173,9 +173,10 @@ function fileExplorer (appAPI, files) { }) function normalize (path, filesList) { + var prefix = path.split('/')[0] var newList = {} Object.keys(filesList).forEach(key => { - newList[path + '/' + key] = filesList[key].isDirectory ? {} : { '/content': true } + newList[prefix + '/' + key] = filesList[key].isDirectory ? {} : { '/content': true } }) return newList }