From bf669ec817cfb554df47f7c15952639d1671019c Mon Sep 17 00:00:00 2001 From: Grandschtroumpf Date: Thu, 14 Mar 2019 13:13:45 +0100 Subject: [PATCH 01/16] Use ApiFactory and a getter for profile. --- src/app.js | 63 +- .../components/plugin-manager-component.js | 33 +- src/app/editor/SourceHighlighters.js | 7 +- src/app/files/remixd-handle.js | 7 +- src/app/panels/file-panel.js | 481 ++++++++------- src/app/tabs/analysis-tab.js | 7 +- src/app/tabs/compile-tab.js | 29 +- src/app/tabs/debugger-tab.js | 8 +- src/app/tabs/run-tab.js | 28 +- src/app/tabs/settings-tab.js | 10 +- src/app/tabs/support-tab.js | 9 +- src/app/tabs/test-tab.js | 9 +- src/app/tabs/txlistener-module.js | 22 + src/app/ui/landing-page/generate.js | 73 --- src/app/ui/landing-page/landing-page.js | 78 ++- src/universal-dapp.js | 580 +++++++++--------- 16 files changed, 744 insertions(+), 700 deletions(-) create mode 100644 src/app/tabs/txlistener-module.js delete mode 100644 src/app/ui/landing-page/generate.js diff --git a/src/app.js b/src/app.js index 5fc3e69559..dcab1213ec 100644 --- a/src/app.js +++ b/src/app.js @@ -7,7 +7,6 @@ var async = require('async') var request = require('request') var remixLib = require('remix-lib') var EventManager = require('./lib/events') -var EventEmitter = require('events') var registry = require('./global/registry') var UniversalDApp = require('./universal-dapp.js') var UniversalDAppUI = require('./universal-dapp-ui.js') @@ -55,8 +54,10 @@ const FilePanel = require('./app/panels/file-panel') import PanelsResize from './lib/panels-resize' import { EntityStore } from './lib/store' import { RemixAppManager } from './remixAppManager' -import { generateHomePage, homepageProfile } from './app/ui/landing-page/generate' +import { LandingPage } from './app/ui/landing-page/landing-page' import framingService from './framingService' +import { ApiFactory } from 'remix-plugin' +import { TxListenerModule } from './app/tabs/txlistener-module' var css = csjs` html { box-sizing: border-box; } @@ -116,8 +117,9 @@ var css = csjs` } ` -class App { +class App extends ApiFactory { constructor (api = {}, events = {}, opts = {}) { + super() var self = this this.event = new EventManager() self._components = {} @@ -173,7 +175,7 @@ class App { run.apply(self) } - profile () { + get profile () { return { name: 'app', description: 'service - provides information about current context (network).', @@ -373,26 +375,13 @@ Please make a backup of your contracts and start using http://remix.ethereum.org /* that proxy is used by appManager to broadcast new transaction event */ - const txListenerModuleProxy = { - event: new EventEmitter(), - profile () { - return { - name: 'txListener', - displayName: 'transaction listener', - events: ['newTransaction'], - description: 'service - notify new transactions' - } - } - } - txlistener.event.register('newTransaction', (tx) => { - txListenerModuleProxy.event.emit('newTransaction', tx) - }) + const txListenerModule = new TxListenerModule(txlistener) txlistener.startListening() // TODO: There are still a lot of dep between editorpanel and filemanager - let appStore = new EntityStore('module', { actives: [], ids: [], entities: {} }) + let appStore = new EntityStore('module', 'name') const appManager = new RemixAppManager(appStore) registry.put({api: appManager, name: 'appmanager'}) @@ -458,33 +447,35 @@ Please make a backup of your contracts and start using http://remix.ethereum.org let settings = new SettingsTab(self._components.registry) let analysis = new AnalysisTab(registry) let debug = new DebuggerTab() + const landingPage = new LandingPage(appManager, appStore) // let support = new SupportTab() let test = new TestTab(self._components.registry, compileTab) let sourceHighlighters = registry.get('editor').api.sourceHighlighters let configProvider = self._components.filesProviders['config'] appManager.init([ - { profile: homepageProfile(), api: generateHomePage(appManager, appStore) }, - { profile: this.profile(), api: this }, - { profile: udapp.profile(), api: udapp }, - { profile: fileManager.profile(), api: fileManager }, - { profile: sourceHighlighters.profile(), api: sourceHighlighters }, - { profile: configProvider.profile(), api: configProvider }, - { profile: txListenerModuleProxy.profile(), api: txListenerModuleProxy }, - { profile: filePanel.profile(), api: filePanel }, + this.api(), + landingPage.api(), + udapp.api(), + fileManager.api(), + sourceHighlighters.api(), + configProvider.api(), + txListenerModule.api(), + filePanel.api(), // { profile: support.profile(), api: support }, - { profile: settings.profile(), api: settings }, - { profile: pluginManagerComponent.profile(), api: pluginManagerComponent }]) + settings.api(), + pluginManagerComponent.api() + ]) appManager.registerMany([ - { profile: compileTab.profile(), api: compileTab }, - { profile: run.profile(), api: run }, - { profile: debug.profile(), api: debug }, - { profile: analysis.profile(), api: analysis }, - { profile: test.profile(), api: test }, - { profile: filePanel.remixdHandle.profile(), api: filePanel.remixdHandle } + compileTab.api(), + run.api(), + debug.api(), + analysis.api(), + test.api(), + filePanel.remixdHandle.api(), + ...appManager.plugins() ]) - appManager.registerMany(appManager.plugins()) framingService.start(appStore, swapPanelApi, verticalIconsApi, mainPanelApi, this._components.resizeFeature) diff --git a/src/app/components/plugin-manager-component.js b/src/app/components/plugin-manager-component.js index 51e5f0ec7f..fe46bc3eb0 100644 --- a/src/app/components/plugin-manager-component.js +++ b/src/app/components/plugin-manager-component.js @@ -2,7 +2,7 @@ const yo = require('yo-yo') const csjs = require('csjs-inject') const EventEmitter = require('events') const LocalPlugin = require('./local-plugin') -import { Plugin } from 'remix-plugin' +import { Plugin, ApiFactory } from 'remix-plugin' const css = csjs` .pluginSearch { @@ -34,9 +34,10 @@ const css = csjs` } ` -class PluginManagerComponent { +class PluginManagerComponent extends ApiFactory { constructor () { + super() this.event = new EventEmitter() this.views = { root: null, @@ -46,7 +47,7 @@ class PluginManagerComponent { this.filter = '' } - profile () { + get profile () { return { displayName: 'plugin manager', name: 'pluginManager', @@ -71,10 +72,10 @@ class PluginManagerComponent { } renderItem (name) { - const mod = this.store.getOne(name) - if (!mod) return + const api = this.store.getOne(name) + if (!api) return const isActive = this.store.actives.includes(name) - const displayName = (mod.profile.displayName) ? mod.profile.displayName : name + const displayName = (api.profile.displayName) ? api.profile.displayName : name const activationButton = isActive ? yo` @@ -92,7 +93,7 @@ class PluginManagerComponent {
${displayName}
${activationButton} -

${mod.profile.description}

+

${api.profile.description}

` } @@ -109,8 +110,8 @@ class PluginManagerComponent { if (!profile) return const resolveLocaton = (iframe) => this.appManager.resolveLocation(profile, iframe) const api = new Plugin(profile, { resolveLocaton }) - this.appManager.registerOne({profile, api}) - this.appManager.activateOne(profile.name) + this.appManager.registerOne(api) + this.appManager.activateOne(api.name) } catch (err) { // TODO : Use an alert to handle this error instead of a console.log console.log(`Cannot create Plugin : ${err.message}`) @@ -119,11 +120,11 @@ class PluginManagerComponent { render () { // Filtering helpers - const isFiltered = ({profile}) => profile.name.toLowerCase().includes(this.filter) + const isFiltered = (api) => api.name.toLowerCase().includes(this.filter) const isNotRequired = ({profile}) => !profile.required const sortByName = (a, b) => { - const nameA = a.profile.name.toUpperCase() - const nameB = b.profile.name.toUpperCase() + const nameA = a.name.toUpperCase() + const nameB = b.name.toUpperCase() return (nameA < nameB) ? -1 : (nameA > nameB) ? 1 : 0 } @@ -132,10 +133,10 @@ class PluginManagerComponent { .filter(isFiltered) .filter(isNotRequired) .sort(sortByName) - .reduce(({actives, inactives}, {profile}) => { - return this.store.actives.includes(profile.name) - ? { actives: [...actives, profile.name], inactives } - : { inactives: [...inactives, profile.name], actives } + .reduce(({actives, inactives}, api) => { + return this.store.actives.includes(api.name) + ? { actives: [...actives, api.name], inactives } + : { inactives: [...inactives, api.name], actives } }, { actives: [], inactives: [] }) const activeTile = actives.length !== 0 diff --git a/src/app/editor/SourceHighlighters.js b/src/app/editor/SourceHighlighters.js index 59243c646a..5d69060a8c 100644 --- a/src/app/editor/SourceHighlighters.js +++ b/src/app/editor/SourceHighlighters.js @@ -1,13 +1,16 @@ 'use strict' const SourceHighlighter = require('./sourceHighlighter') -class SourceHighlighters { +import { ApiFactory } from 'remix-plugin' + +class SourceHighlighters extends ApiFactory { constructor () { + super() this.highlighters = {} } - profile () { + get profile () { return { displayName: 'source highlighters', name: 'sourceHighlighters', diff --git a/src/app/files/remixd-handle.js b/src/app/files/remixd-handle.js index 19b62947fc..1cc02c28f4 100644 --- a/src/app/files/remixd-handle.js +++ b/src/app/files/remixd-handle.js @@ -1,3 +1,5 @@ +import { ApiFactory } from 'remix-plugin' + var yo = require('yo-yo') var modalDialog = require('../ui/modaldialog') @@ -14,13 +16,14 @@ var css = csjs` } ` -export class RemixdHandle { +export class RemixdHandle extends ApiFactory { constructor (fileSystemExplorer, locahostProvider) { + super() this.fileSystemExplorer = fileSystemExplorer this.locahostProvider = locahostProvider } - profile () { + get profile () { return { name: 'remixd', methods: [], diff --git a/src/app/panels/file-panel.js b/src/app/panels/file-panel.js index 47abfc628c..154171f562 100644 --- a/src/app/panels/file-panel.js +++ b/src/app/panels/file-panel.js @@ -17,6 +17,8 @@ var globalRegistry = require('../../global/registry') var css = require('./styles/file-panel-styles') +import { ApiFactory } from 'remix-plugin' + var canUpload = window.File || window.FileReader || window.FileList || window.Blob /* @@ -36,285 +38,289 @@ var canUpload = window.File || window.FileReader || window.FileList || window.Bl - call fileProvider API */ -function filepanel (localRegistry) { - var self = this - self._components = {} - self._components.registry = localRegistry || globalRegistry - self._deps = { - fileProviders: self._components.registry.get('fileproviders').api, - fileManager: self._components.registry.get('filemanager').api, - config: self._components.registry.get('config').api, - pluginManager: self._components.registry.get('pluginmanager').api - } - var fileExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['browser']) - var fileSystemExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['localhost']) - var swarmExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['swarm']) - var githubExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['github']) - var gistExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['gist']) - var configExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['config']) - var httpExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['http']) - var httpsExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['https']) - - self.remixdHandle = new RemixdHandle(fileSystemExplorer, self._deps.fileProviders['localhost']) - - // ----------------- editor panel ---------------------- - self._compilerMetadata = new CompilerMetadata( - { - fileManager: self._deps.fileManager, - pluginManager: self._deps.pluginManager, - config: self._deps.config +module.exports = class Filepanel extends ApiFactory { + + constructor (localRegistry) { + super() + var self = this + self._components = {} + self._components.registry = localRegistry || globalRegistry + self._deps = { + fileProviders: self._components.registry.get('fileproviders').api, + fileManager: self._components.registry.get('filemanager').api, + config: self._components.registry.get('config').api, + pluginManager: self._components.registry.get('pluginmanager').api } - ) - self._compilerMetadata.syncContractMetadata() - - self.compilerMetadata = () => { return self._compilerMetadata } - - function template () { - return yo` -
-
-
- - - - ${canUpload ? yo` - - + var fileExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['browser']) + var fileSystemExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['localhost']) + var swarmExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['swarm']) + var githubExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['github']) + var gistExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['gist']) + var configExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['config']) + var httpExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['http']) + var httpsExplorer = new FileExplorer(self._components.registry, self._deps.fileProviders['https']) + + self.remixdHandle = new RemixdHandle(fileSystemExplorer, self._deps.fileProviders['localhost']) + + // ----------------- editor panel ---------------------- + self._compilerMetadata = new CompilerMetadata( + { + fileManager: self._deps.fileManager, + pluginManager: self._deps.pluginManager, + config: self._deps.config + } + ) + self._compilerMetadata.syncContractMetadata() + + self.compilerMetadata = () => { return self._compilerMetadata } + + function template () { + return yo` +
+
+
+ + - ` : ''} - publishToGist('browser')}> - - - updateGist()}> - - - - - -
-
-
${fileExplorer.init()}
-
${configExplorer.init()}
-
${fileSystemExplorer.init()}
-
${swarmExplorer.init()}
-
${githubExplorer.init()}
-
${gistExplorer.init()}
-
${httpExplorer.init()}
-
${httpsExplorer.init()}
+ ${canUpload ? yo` + + + + ` : ''} + publishToGist('browser')}> + + + updateGist()}> + + + + + +
+
+
${fileExplorer.init()}
+
${configExplorer.init()}
+
${fileSystemExplorer.init()}
+
${swarmExplorer.init()}
+
${githubExplorer.init()}
+
${gistExplorer.init()}
+
${httpExplorer.init()}
+
${httpsExplorer.init()}
+
-
- ` - } + ` + } - var event = new EventManager() - self.event = event - var element = template() - fileExplorer.ensureRoot() - configExplorer.ensureRoot() - self._deps.fileProviders['localhost'].event.register('connecting', (event) => { - }) + var event = new EventManager() + self.event = event + var element = template() + fileExplorer.ensureRoot() + configExplorer.ensureRoot() + self._deps.fileProviders['localhost'].event.register('connecting', (event) => { + }) - self._deps.fileProviders['localhost'].event.register('connected', (event) => { - fileSystemExplorer.show() - }) + self._deps.fileProviders['localhost'].event.register('connected', (event) => { + fileSystemExplorer.show() + }) - self._deps.fileProviders['localhost'].event.register('errored', (event) => { - fileSystemExplorer.hide() - }) + self._deps.fileProviders['localhost'].event.register('errored', (event) => { + fileSystemExplorer.hide() + }) - self._deps.fileProviders['localhost'].event.register('closed', (event) => { - fileSystemExplorer.hide() - }) + self._deps.fileProviders['localhost'].event.register('closed', (event) => { + fileSystemExplorer.hide() + }) - fileExplorer.events.register('focus', function (path) { - self._deps.fileManager.switchFile(path) - }) + fileExplorer.events.register('focus', function (path) { + self._deps.fileManager.switchFile(path) + }) - configExplorer.events.register('focus', function (path) { - self._deps.fileManager.switchFile(path) - }) + configExplorer.events.register('focus', function (path) { + self._deps.fileManager.switchFile(path) + }) - fileSystemExplorer.events.register('focus', function (path) { - self._deps.fileManager.switchFile(path) - }) + fileSystemExplorer.events.register('focus', function (path) { + self._deps.fileManager.switchFile(path) + }) - swarmExplorer.events.register('focus', function (path) { - self._deps.fileManager.switchFile(path) - }) + swarmExplorer.events.register('focus', function (path) { + self._deps.fileManager.switchFile(path) + }) - githubExplorer.events.register('focus', function (path) { - self._deps.fileManager.switchFile(path) - }) + githubExplorer.events.register('focus', function (path) { + self._deps.fileManager.switchFile(path) + }) - gistExplorer.events.register('focus', function (path) { - self._deps.fileManager.switchFile(path) - }) + gistExplorer.events.register('focus', function (path) { + self._deps.fileManager.switchFile(path) + }) - httpExplorer.events.register('focus', function (path) { - self._deps.fileManager.switchFile(path) - }) + httpExplorer.events.register('focus', function (path) { + self._deps.fileManager.switchFile(path) + }) - httpsExplorer.events.register('focus', function (path) { - self._deps.fileManager.switchFile(path) - }) + httpsExplorer.events.register('focus', function (path) { + self._deps.fileManager.switchFile(path) + }) - self.render = function render () { return element } + self.render = function render () { return element } + + function uploadFile (event) { + // TODO The file explorer is merely a view on the current state of + // 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((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.event.trigger('focus', [name]) + } + fileReader.readAsText(file) + } - self.profile = function () { - return { - name: 'fileExplorers', - displayName: 'file explorers', - methods: [], - events: [], - icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4=', - description: ' - ', - kind: 'fileexplorer' + var name = files.type + '/' + file.name + files.exists(name, (error, exist) => { + if (error) console.log(error) + if (!exist) { + loadFile() + } else { + modalDialogCustom.confirm(null, `The file ${name} already exists! Would you like to overwrite it?`, () => { loadFile() }) + } + }) + }) } - } - function uploadFile (event) { - // TODO The file explorer is merely a view on the current state of - // 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((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 + function createNewFile () { + modalDialogCustom.prompt(null, 'File Name', 'Untitled.sol', (input) => { + helper.createNonClashingName(input, self._deps.fileProviders['browser'], (error, newName) => { + if (error) return modalDialogCustom.alert('Failed to create file ' + newName + ' ' + error) + if (!self._deps.fileProviders['browser'].set(newName, '')) { + modalDialogCustom.alert('Failed to create file ' + newName) + } else { + var file = self._deps.fileProviders['browser'].type + '/' + newName + self._deps.fileManager.switchFile(file) + if (file.includes('_test.sol')) { + self.event.trigger('newTestFileCreated', [file]) + } } - var success = files.set(name, event.target.result) - if (!success) modalDialogCustom.alert('Failed to create file ' + name) - else self.event.trigger('focus', [name]) - } - fileReader.readAsText(file) + }) + }, null, true) + } + + // ------------------ gist publish -------------- + + function updateGist () { + var gistId = self._deps.fileProviders['gist'].id + if (!gistId) { + tooltip('no gist content is currently loaded.') + } else { + toGist('gist', gistId) } + } - var name = files.type + '/' + file.name - files.exists(name, (error, exist) => { - if (error) console.log(error) - if (!exist) { - loadFile() - } else { - modalDialogCustom.confirm(null, `The file ${name} already exists! Would you like to overwrite it?`, () => { loadFile() }) - } + function publishToGist (fileProviderName) { + modalDialogCustom.confirm(null, 'Are you very sure you want to publish all your files anonymously as a public gist on github.com?', () => { + toGist(fileProviderName) }) - }) - } + } - function createNewFile () { - modalDialogCustom.prompt(null, 'File Name', 'Untitled.sol', (input) => { - helper.createNonClashingName(input, self._deps.fileProviders['browser'], (error, newName) => { - if (error) return modalDialogCustom.alert('Failed to create file ' + newName + ' ' + error) - if (!self._deps.fileProviders['browser'].set(newName, '')) { - modalDialogCustom.alert('Failed to create file ' + newName) + function toGist (fileProviderName, id) { + packageFiles(self._deps.fileProviders[fileProviderName], (error, packaged) => { + if (error) { + console.log(error) + modalDialogCustom.alert('Failed to create gist: ' + error) } else { - var file = self._deps.fileProviders['browser'].type + '/' + newName - self._deps.fileManager.switchFile(file) - if (file.includes('_test.sol')) { - self.event.trigger('newTestFileCreated', [file]) + var tokenAccess = self._deps.config.get('settings/gist-access-token') + if (!tokenAccess) { + modalDialogCustom.alert('Remix requires an access token (which includes gists creation permission). Please go to the settings tab for more information.') + } else { + var description = 'Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. \n Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=' + queryParams.get().version + '&optimize=' + queryParams.get().optimize + '&gist=' + var gists = new Gists({ + token: tokenAccess + }) + if (id) { + tooltip('Saving gist (' + id + ') ...') + gists.edit({ + description: description, + public: true, + files: packaged, + id: id + }, (error, result) => { + cb(error, result) + }) + } else { + tooltip('Creating a new gist ...') + gists.create({ + description: description, + public: true, + files: packaged + }, (error, result) => { + cb(error, result) + }) + } } } }) - }, null, true) - } - - // ------------------ gist publish -------------- - - function updateGist () { - var gistId = self._deps.fileProviders['gist'].id - if (!gistId) { - tooltip('no gist content is currently loaded.') - } else { - toGist('gist', gistId) } - } - - function publishToGist (fileProviderName) { - modalDialogCustom.confirm(null, 'Are you very sure you want to publish all your files anonymously as a public gist on github.com?', () => { - toGist(fileProviderName) - }) - } - function toGist (fileProviderName, id) { - packageFiles(self._deps.fileProviders[fileProviderName], (error, packaged) => { + function cb (error, data) { if (error) { - console.log(error) - modalDialogCustom.alert('Failed to create gist: ' + error) + modalDialogCustom.alert('Failed to manage gist: ' + error) } else { - var tokenAccess = self._deps.config.get('settings/gist-access-token') - if (!tokenAccess) { - modalDialogCustom.alert('Remix requires an access token (which includes gists creation permission). Please go to the settings tab for more information.') - } else { - var description = 'Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. \n Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=' + queryParams.get().version + '&optimize=' + queryParams.get().optimize + '&gist=' - var gists = new Gists({ - token: tokenAccess + if (data.html_url) { + modalDialogCustom.confirm(null, `The gist is at ${data.html_url}. Would you like to open it in a new window?`, () => { + window.open(data.html_url, '_blank') }) - if (id) { - tooltip('Saving gist (' + id + ') ...') - gists.edit({ - description: description, - public: true, - files: packaged, - id: id - }, (error, result) => { - cb(error, result) - }) - } else { - tooltip('Creating a new gist ...') - gists.create({ - description: description, - public: true, - files: packaged - }, (error, result) => { - cb(error, result) - }) - } + } else { + modalDialogCustom.alert(data.message + ' ' + data.documentation_url + ' ' + JSON.stringify(data.errors, null, '\t')) } } - }) - } + } + + // ------------------ copy files -------------- - function cb (error, data) { - if (error) { - modalDialogCustom.alert('Failed to manage gist: ' + error) - } else { - if (data.html_url) { - modalDialogCustom.confirm(null, `The gist is at ${data.html_url}. Would you like to open it in a new window?`, () => { - window.open(data.html_url, '_blank') + function copyFiles () { + modalDialogCustom.prompt(null, 'To which other remix-ide instance do you want to copy over all files?', 'https://remix.ethereum.org', (target) => { + doCopy(target) + }) + function doCopy (target) { + // package only files from the browser storage. + packageFiles(self._deps.fileProviders['browser'], (error, packaged) => { + if (error) { + console.log(error) + } else { + $('