diff --git a/package.json b/package.json index 5e70cf596f..de9330fb41 100644 --- a/package.json +++ b/package.json @@ -67,8 +67,8 @@ "yo-yoify": "^3.7.3" }, "dependencies": { - "http-server": "^0.11.1", "remix-plugin": "0.0.2-alpha.6", + "http-server": "^0.11.1", "remixd": "0.1.8-alpha.6" }, "repository": { diff --git a/src/app.js b/src/app.js index 5028e36b74..545677e4d3 100644 --- a/src/app.js +++ b/src/app.js @@ -33,12 +33,6 @@ var TransactionReceiptResolver = require('./transactionReceiptResolver') const PluginManagerComponent = require('./app/components/plugin-manager-component') -const VerticalIconsComponent = require('./app/components/vertical-icons-component') -const VerticalIconsApi = require('./app/components/vertical-icons-api') - -const SwapPanelComponent = require('./app/components/swap-panel-component') -const SwapPanelApi = require('./app/components/swap-panel-api') - const CompileTab = require('./app/tabs/compile-tab') const SettingsTab = require('./app/tabs/settings-tab') const AnalysisTab = require('./app/tabs/analysis-tab') @@ -55,6 +49,9 @@ import framingService from './framingService' import { MainView } from './app/panels/main-view' import { ThemeModule } from './app/tabs/theme-module' import { NetworkModule } from './app/tabs/network-module' +import { SwapPanel } from './app/components/swap-panel' +import { MainPanel } from './app/components/main-panel' +import { VerticalIcons } from './app/components/vertical-icons' var css = csjs` html { box-sizing: border-box; } @@ -324,8 +321,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org const appManager = new RemixAppManager(appStore) registry.put({api: appManager, name: 'appmanager'}) - const mainPanelComponent = new SwapPanelComponent('mainPanel', appStore, appManager, { default: false, displayHeader: false }) - // ----------------- file manager ---------------------------- self._components.fileManager = new FileManager() const fileManager = self._components.fileManager @@ -339,8 +334,19 @@ Please make a backup of your contracts and start using http://remix.ethereum.org const themeModule = new ThemeModule(registry) registry.put({api: themeModule, name: 'themeModule'}) + // ----------------- landing page ---------------------------- + // Need to have Home initialized before VerticalIconComponent render to access profile of it for icon + const landingPage = new LandingPage(appManager, appStore) + + // ----------------- Vertical Icon ---------------------------- + const verticalIcons = new VerticalIcons('swapPanel', appStore, landingPage) + registry.put({api: verticalIcons, name: 'verticalicon'}) + + const swapPanel = new SwapPanel(appStore) + const mainPanel = new MainPanel(appStore) + // ----------------- main view ---------------------- - self._components.mainview = new MainView(appStore, appManager, mainPanelComponent) + self._components.mainview = new MainView(appStore, appManager, mainPanel) registry.put({ api: self._components.mainview, name: 'mainview' }) // ----------------- Renderer ----------------- @@ -359,27 +365,17 @@ Please make a backup of your contracts and start using http://remix.ethereum.org // TODOs those are instanciated before hand. should be instanciated on demand const pluginManagerComponent = new PluginManagerComponent() - const swapPanelComponent = new SwapPanelComponent('swapPanel', appStore, appManager, { default: true, displayHeader: true }) registry.put({api: appManager.proxy(), name: 'pluginmanager'}) pluginManagerComponent.setApp(appManager) pluginManagerComponent.setStore(appStore) - // Need to have Home initialized before VerticalIconComponent render to access profile of it for icon - const landingPage = new LandingPage(appManager, appStore) - - // ----------------- Vertical Icon ---------------------------- - const verticalIconsComponent = new VerticalIconsComponent('swapPanel', appStore, landingPage.profile) - const swapPanelApi = new SwapPanelApi(swapPanelComponent, verticalIconsComponent) // eslint-disable-line - const mainPanelApi = new SwapPanelApi(mainPanelComponent, verticalIconsComponent) // eslint-disable-line - const verticalIconsApi = new VerticalIconsApi(verticalIconsComponent) // eslint-disable-line - registry.put({api: verticalIconsApi, name: 'verticalicon'}) - self._components.mainview.init() + self._components.fileManager.init() self._view.mainpanel.appendChild(self._components.mainview.render()) - self._view.iconpanel.appendChild(verticalIconsComponent.render()) - self._view.swappanel.appendChild(swapPanelComponent.render()) + self._view.iconpanel.appendChild(verticalIcons.render()) + self._view.swappanel.appendChild(swapPanel.render()) let filePanel = new FilePanel() registry.put({api: filePanel, name: 'filepanel'}) @@ -423,7 +419,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org fileManager.api(), sourceHighlighters.api(), filePanel.api(), - // { profile: support.profile(), api: support }, settings.api(), pluginManagerComponent.api(), networkModule.api(), @@ -440,7 +435,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org ...appManager.plugins() ]) - framingService.start(appStore, swapPanelApi, verticalIconsApi, mainPanelApi, this._components.resizeFeature) + framingService.start(appStore, swapPanel, verticalIcons, mainPanel, this._components.resizeFeature) // The event listener needs to be registered as early as possible, because the // parent will send the message upon the "load" event. @@ -467,7 +462,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org txLogger.event.register('debuggingRequested', (hash) => { if (!appStore.isActive('debugger')) appManager.activateOne('debugger') debug.debugger().debug(hash) - verticalIconsApi.select('debugger') + verticalIcons.select('debugger') }) let transactionContextAPI = { diff --git a/src/app/components/main-panel.js b/src/app/components/main-panel.js new file mode 100644 index 0000000000..d9813493f9 --- /dev/null +++ b/src/app/components/main-panel.js @@ -0,0 +1,24 @@ +import { AbstractPanel } from './panel' +const yo = require('yo-yo') +const csjs = require('csjs-inject') + +const css = csjs` + .pluginsContainer { + height: 100%; + display: flex; + overflow-y: hidden; + } +` + +export class MainPanel extends AbstractPanel { + constructor (appStore, options) { + super('mainPanel', appStore, options) + } + + render () { + return yo` +
+ ${this.view} +
` + } +} diff --git a/src/app/components/panel.js b/src/app/components/panel.js new file mode 100644 index 0000000000..abee8c03e7 --- /dev/null +++ b/src/app/components/panel.js @@ -0,0 +1,111 @@ +import { EventEmitter } from 'events' +const registry = require('../../global/registry') +const csjs = require('csjs-inject') +const yo = require('yo-yo') + +const css = csjs` + .plugins { + height: 100%; + } + .plugItIn { + display : none; + height : 100%; + } + .plugItIn > div { + overflow-y : auto; + height : 100%; + width : 100%; + } + .plugItIn.active { + display : block; + } + .pluginsContainer { + height: 100%; + overflow-y: hidden; + } +` + +// Events are : 'toggle' | 'showing' + +/** Abstract class used for hosting the view of a plugin */ +export class AbstractPanel { + + constructor (panelName, appStore, opts) { + this.events = new EventEmitter() + this.contents = {} + this.active = undefined + + // View where the plugin HTMLElement leaves + this.view = yo`
` + + appStore.event.on('activate', (name) => { + const api = appStore.getOne(name) + const profile = api.profile + if (profile.location !== panelName) return + if (!profile.location && !opts.default) return + if (profile.icon && api.render && typeof api.render === 'function') { + this.add(name, api.render()) + } + }) + + appStore.event.on('deactivate', (name) => { + if (this.contents[name]) this.remove(name) + }) + + const verticalIcon = registry.get('verticalicon').api + // Toggle content + verticalIcon.events.on('toggleContent', (name) => { + if (!this.contents[name]) return + if (this.active === name) { + this.events.emit('toggle', name) + } + this.showContent(name) + this.events.emit('showing', name) + }) + // Force opening + verticalIcon.events.on('showContent', (name) => { + if (!this.contents[name]) return + this.showContent(name) + this.events.emit('showing', name) + }) + } + + /** + * Add the plugin to the panel + * @param {String} name the name of the plugin + * @param {HTMLElement} content the HTMLContent of the plugin + */ + add (name, content) { + if (this.contents[name]) throw new Error(`Plugin ${name} already rendered`) + content.style.height = '100%' + content.style.width = '100%' + content.style.border = '0' + this.contents[name] = yo`
${content}
` + this.view.appendChild(this.contents[name]) + } + + /** + * Remove a plugin from the panel + * @param {String} name The name of the plugin to remove + */ + remove (name) { + const el = this.contents[name] + delete this.contents[name] + if (el) el.parentElement.removeChild(el) + } + + /** + * Display the content of this specific plugin + * @param {String} name The name of the plugin to display the content + */ + showContent (name) { + if (!this.contents[name]) throw new Error(`Plugin ${name} is not yet activated`) + // hiding the current view and display the `moduleName` + if (this.active) { + this.contents[this.active].style.display = 'none' + } + this.contents[name].style.display = 'block' + this.active = name + } +} + diff --git a/src/app/components/swap-panel-api.js b/src/app/components/swap-panel-api.js deleted file mode 100644 index e1f8c1c5e6..0000000000 --- a/src/app/components/swap-panel-api.js +++ /dev/null @@ -1,43 +0,0 @@ -import EventEmmitter from 'events' - -class SwapPanelApi { - constructor (swapPanelComponent, verticalIconsComponent) { - this.event = new EventEmmitter() - this.component = swapPanelComponent - this.currentContent - verticalIconsComponent.events.on('toggleContent', (moduleName) => { - if (!swapPanelComponent.contents[moduleName]) return - if (this.currentContent === moduleName) { - this.event.emit('toggle', moduleName) - return - } - this.showContent(moduleName) - this.event.emit('showing', moduleName) - }) - - verticalIconsComponent.events.on('showContent', (moduleName) => { - if (!swapPanelComponent.contents[moduleName]) return - this.showContent(moduleName) - this.event.emit('showing', moduleName) - }) - } - - showContent (moduleName) { - this.component.showContent(moduleName) - this.currentContent = moduleName - } - - /* - content: DOM element - by appManager - */ - add (profile, content) { - return this.component.add(profile.name, content) - } - - remove (profile) { - return this.component.remove(profile.name) - } -} - -module.exports = SwapPanelApi diff --git a/src/app/components/swap-panel-component.js b/src/app/components/swap-panel-component.js deleted file mode 100644 index 1608db3ee4..0000000000 --- a/src/app/components/swap-panel-component.js +++ /dev/null @@ -1,102 +0,0 @@ -var yo = require('yo-yo') -var csjs = require('csjs-inject') - -class SwapPanelComponent { - constructor (name, appStore, appManager, opt) { - this.name = name - this.opt = opt - this.store = appStore - // list of contents - this.contents = {} - // name of the current displayed content - this.currentNode - - this.store.event.on('activate', (name) => { - const api = this.store.getOne(name) - const profile = api.profile - if (((profile.location === this.name) || (!profile.location && opt.default)) && - profile.icon && api.render && typeof api.render === 'function') { - this.add(name, api.render()) - } - }) - - this.store.event.on('deactivate', (name) => { - if (this.contents[name]) this.remove(name) - }) - this.store.event.on('add', (api) => { }) - this.store.event.on('remove', (api) => { }) - } - - showContent (moduleName) { - // hiding the current view and display the `moduleName` - if (this.contents[moduleName]) { - if (this.currentNode) { - this.contents[this.currentNode].style.display = 'none' - } - this.contents[moduleName].style.display = 'block' - this.currentNode = moduleName - var api = this.store.getOne(moduleName) - this.header.querySelector('h6').innerHTML = api.profile ? api.profile.displayName : ' - ' - return - } - } - - add (moduleName, content) { - content.style.height = '100%' - content.style.width = '100%' - content.style.border = '0' - this.contents[moduleName] = yo`
${content}
` - this.view.appendChild(this.contents[moduleName]) - } - - remove (moduleName) { - let el = this.contents[moduleName] - if (el) el.parentElement.removeChild(el) - } - - render () { - this.view = yo` -
-
- ` - this.header = yo`
` - if (!this.opt.displayHeader) this.header.style.display = 'none' - - return yo`
- ${this.header} - ${this.view} -
` - } -} - -module.exports = SwapPanelComponent - -const css = csjs` - .plugins { - height : 95%; - } - .plugItIn { - display : none; - height : 100%; - } - .plugItIn > div { - overflow-y : auto; - height : 100%; - width : 100%; - } - .plugItIn.active { - display : block; - } - .pluginsContainer { - height: 100%; - overflow-y: hidden; - } - .swapitTitle { - text-transform: uppercase; - } - .swapitHeader { - height: 35px; - padding-top: 10px; - padding-left: 27px; - } -` diff --git a/src/app/components/swap-panel.js b/src/app/components/swap-panel.js new file mode 100644 index 0000000000..1f7de07c88 --- /dev/null +++ b/src/app/components/swap-panel.js @@ -0,0 +1,84 @@ +import { AbstractPanel } from './panel' +const csjs = require('csjs-inject') +const yo = require('yo-yo') + +const css = csjs` + .panel { + height: 100%; + overflow-y: hidden; + } + .swapitTitle { + text-transform: uppercase; + } + .swapitHeader { + height: 35px; + padding: 0 20px; + display: flex; + justify-content: space-between; + align-items: center; + } + .swapitHeader h6 { + margin: 0; + } + .icons i { + height: 80%; + cursor: pointer; + } + .pluginsContainer { + height: calc(100% - 35px); + overflow: auto; + } +` + +const options = { + default: true, + displayHeader: true +} + +export class SwapPanel extends AbstractPanel { + + constructor (appStore) { + super('swapPanel', appStore, options) + this.header = this.renderHeader() + this.store = appStore + } + + /** + * Display content and update the header + * @param {String} name The name of the plugin to display + */ + showContent (name) { + super.showContent(name) + yo.update(this.header, this.renderHeader()) + } + + /** The header of the swap panel */ + renderHeader () { + let name = ' - ' + let hasSettings = false + if (this.active) { + const { profile } = this.store.getOne(this.active) + name = profile.displayName ? profile.displayName : profile.name + hasSettings = profile.settings || false + } + return yo` +
+
${name}
+
+ ${hasSettings + ? yo`` + : yo``} +
+
` + } + + render () { + return yo` +
+ ${this.header} +
+ ${this.view} +
+
` + } +} diff --git a/src/app/components/vertical-icons-api.js b/src/app/components/vertical-icons-api.js deleted file mode 100644 index 9cfe989471..0000000000 --- a/src/app/components/vertical-icons-api.js +++ /dev/null @@ -1,20 +0,0 @@ -// API -class VerticalIconsApi { - - constructor (verticalIconsComponent) { - this.component = verticalIconsComponent - } - - addIcon (mod) { - this.component.addIcon(mod) - } - - removeIcon (mod) { - this.component.removeIcon(mod) - } - - select (moduleName) { - this.component.select(moduleName) - } -} -module.exports = VerticalIconsApi diff --git a/src/app/components/vertical-icons-component.js b/src/app/components/vertical-icons.js similarity index 99% rename from src/app/components/vertical-icons-component.js rename to src/app/components/vertical-icons.js index cabe2b305c..32a96b7500 100644 --- a/src/app/components/vertical-icons-component.js +++ b/src/app/components/vertical-icons.js @@ -6,7 +6,7 @@ let globalRegistry = require('../../global/registry') const EventEmitter = require('events') // Component -class VerticalIconComponent { +export class VerticalIcons { constructor (name, appStore, homeProfile) { this.store = appStore @@ -78,7 +78,7 @@ class VerticalIconComponent { this.icons[name] = yo`
${name}
` @@ -359,8 +359,6 @@ class VerticalIconComponent { } } -module.exports = VerticalIconComponent - const css = csjs` .homeIcon { display: block; diff --git a/src/app/panels/main-view.js b/src/app/panels/main-view.js index d2bcb4a55c..68980cf251 100644 --- a/src/app/panels/main-view.js +++ b/src/app/panels/main-view.js @@ -28,7 +28,7 @@ var css = csjs` ` export class MainView { - constructor (appStore, appManager, mainPanelComponent) { + constructor (appStore, appManager, mainPanel) { var self = this self.event = new EventManager() self._view = {} @@ -38,7 +38,7 @@ export class MainView { self._components.registry.put({api: self._components.editor, name: 'editor'}) self.appStore = appStore self.appManager = appManager - self.mainPanelComponent = mainPanelComponent + self.mainPanel = mainPanel } init () { var self = this @@ -52,7 +52,7 @@ export class MainView { self.tabProxy = new TabProxy(self._deps.fileManager, self._components.editor, self.appStore, self.appManager) let showApp = function (name) { self._deps.fileManager.unselectCurrentFile() - self.mainPanelComponent.showContent(name) + self.mainPanel.showContent(name) self._view.editor.style.display = 'none' self._components.contextView.hide() self._view.mainPanel.style.display = 'block' @@ -178,7 +178,7 @@ export class MainView { if (self._view.el) return self._view.el self._view.editor = self._components.editor.render() self._view.editor.style.display = 'none' - self._view.mainPanel = self.mainPanelComponent.render() + self._view.mainPanel = self.mainPanel.render() self._view.terminal = self._components.terminal.render() self._view.content = yo`
diff --git a/src/app/ui/landing-page/landing-page.js b/src/app/ui/landing-page/landing-page.js index c5abf2e7ae..d55e8d31f9 100644 --- a/src/app/ui/landing-page/landing-page.js +++ b/src/app/ui/landing-page/landing-page.js @@ -17,7 +17,6 @@ let css = csjs` text-decoration: underline; } .homeContainer { - height: 105%!important; /* @todo should be removed once swap_it and mainview will be separated */ user-select:none; } .jumbotronContainer { diff --git a/src/framingService.js b/src/framingService.js index 7bfbfd066e..f35dd3a48d 100644 --- a/src/framingService.js +++ b/src/framingService.js @@ -1,27 +1,26 @@ export default { - start: (appStore, swapPanelApi, verticalIconApi, mainPanelApi, resizeFeature) => { - swapPanelApi.event.on('toggle', () => { + start: (appStore, swapPanel, verticalIcon, mainPanel, resizeFeature) => { + swapPanel.events.on('toggle', () => { resizeFeature.panel1.clientWidth !== 0 ? resizeFeature.minimize() : resizeFeature.maximise() }) - swapPanelApi.event.on('showing', () => { + swapPanel.events.on('showing', () => { resizeFeature.panel1.clientWidth === 0 ? resizeFeature.maximise() : '' }) - mainPanelApi.event.on('toggle', () => { + mainPanel.events.on('toggle', () => { resizeFeature.maximise() }) - // mainPanelApi.event.on('showing', (moduleName) => {}) - verticalIconApi.select('fileExplorers') - mainPanelApi.showContent('home') + verticalIcon.select('fileExplorers') + mainPanel.showContent('home') document.addEventListener('keypress', (e) => { if (e.shiftKey && e.ctrlKey) { if (e.code === 'KeyF') { // Ctrl+Shift+F - verticalIconApi.select('fileExplorers') + verticalIcon.select('fileExplorers') } else if (e.code === 'KeyA') { // Ctrl+Shift+A - verticalIconApi.select('pluginManager') + verticalIcon.select('pluginManager') } else if (e.code === 'KeyS') { // Ctrl+Shift+S - verticalIconApi.select('settings') + verticalIcon.select('settings') } e.preventDefault() }