diff --git a/extensions/etherscan-general/index.js b/extensions/etherscan-general/index.js
index f5a8ffd17c..cb189cdf8d 100644
--- a/extensions/etherscan-general/index.js
+++ b/extensions/etherscan-general/index.js
@@ -40,7 +40,7 @@ function load () {
}
})
setInterval(function () {
- remix.call('app', 'detectNetWork', [], function (error, result) {
+ remix.call('network', 'detectNetWork', [], function (error, result) {
if (error) console.log(error)
if (network.innerHTML !== result[0].name + ' - ' + result[0].id) {
currentNetWork = result[0].name
diff --git a/package.json b/package.json
index 5a2957f12d..f2e5a76d0a 100644
--- a/package.json
+++ b/package.json
@@ -65,7 +65,7 @@
},
"dependencies": {
"http-server": "0.9.0",
- "remix-plugin": "0.0.1-alpha.43",
+ "remix-plugin": "0.0.2-alpha.3",
"remixd": "0.1.8-alpha.6"
},
"repository": {
diff --git a/src/app.js b/src/app.js
index a0e6475f79..e4ef25e021 100644
--- a/src/app.js
+++ b/src/app.js
@@ -6,7 +6,6 @@ var yo = require('yo-yo')
var async = require('async')
var request = require('request')
var remixLib = require('remix-lib')
-var EventManager = require('./lib/events')
var registry = require('./global/registry')
var UniversalDApp = require('./universal-dapp.js')
var UniversalDAppUI = require('./universal-dapp-ui.js')
@@ -54,9 +53,8 @@ import { EntityStore } from './lib/store'
import { RemixAppManager } from './remixAppManager'
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'
import { ThemeModule } from './app/tabs/theme-module'
+import { NetworkModule } from './app/tabs/network-module'
var css = csjs`
html { box-sizing: border-box; }
@@ -116,11 +114,9 @@ var css = csjs`
}
`
-class App extends ApiFactory {
+class App {
constructor (api = {}, events = {}, opts = {}) {
- super()
var self = this
- this.event = new EventManager()
self._components = {}
registry.put({api: self, name: 'app'})
@@ -167,18 +163,10 @@ class App extends ApiFactory {
init () {
var self = this
- self._components.resizeFeature = new PanelsResize('#swap-panel', '#editor-container', { 'minWidth': 300, x: 300 })
+ self._components.resizeFeature = new PanelsResize('#swap-panel', '#editor-container', { 'minWidth': 300, x: 450 })
run.apply(self)
}
- get profile () {
- return {
- name: 'app',
- description: 'service - provides information about current context (network).',
- methods: ['getExecutionContextProvider', 'getProviderEndpoint', 'detectNetWork', 'addProvider', 'removeProvider']
- }
- }
-
render () {
var self = this
if (self._view.el) return self._view.el
@@ -250,45 +238,6 @@ class App extends ApiFactory {
if (callback) callback(error)
})
}
-
- getExecutionContextProvider () {
- return new Promise((resolve, reject) => {
- resolve(executionContext.getProvider())
- })
- }
-
- getProviderEndpoint () {
- return new Promise((resolve, reject) => {
- if (executionContext.getProvider() === 'web3') {
- resolve(executionContext.web3().currentProvider.host)
- } else {
- reject('no endpoint: current provider is either injected or vm')
- }
- })
- }
-
- detectNetWork () {
- return new Promise((resolve, reject) => {
- executionContext.detectNetwork((error, network) => {
- if (error) return reject(error)
- resolve(network)
- })
- })
- }
-
- addProvider (name, url) {
- return new Promise((resolve, reject) => {
- executionContext.addProvider({ name, url })
- resolve()
- })
- }
-
- removeProvider (name) {
- return new Promise((resolve, reject) => {
- executionContext.removeProvider(name)
- resolve()
- })
- }
}
module.exports = App
@@ -329,7 +278,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
registry.put({api: self._components.compilersArtefacts, name: 'compilersartefacts'})
// ----------------- UniversalDApp -----------------
- var udapp = new UniversalDApp(registry)
+ const udapp = new UniversalDApp(registry)
// TODO: to remove when possible
registry.put({api: udapp, name: 'udapp'})
udapp.event.register('transactionBroadcasted', (txhash, networkName) => {
@@ -337,14 +286,14 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
if (txLink) registry.get('logCallback').api.logCallback(yo`${txLink}`)
})
- var udappUI = new UniversalDAppUI(udapp, registry)
+ const udappUI = new UniversalDAppUI(udapp, registry)
// TODO: to remove when possible
registry.put({api: udappUI, name: 'udappUI'})
// ----------------- Tx listener -----------------
- var transactionReceiptResolver = new TransactionReceiptResolver()
+ const transactionReceiptResolver = new TransactionReceiptResolver()
- var txlistener = new Txlistener({
+ const txlistener = new Txlistener({
api: {
contracts: function () {
if (self._components.compilersArtefacts['__last']) return self._components.compilersArtefacts['__last'].getContracts()
@@ -358,8 +307,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
udapp: udapp.event
}})
registry.put({api: txlistener, name: 'txlistener'})
+ udapp.startListening(txlistener)
- var eventsDecoder = new EventsDecoder({
+ const eventsDecoder = new EventsDecoder({
api: {
resolveReceipt: function (tx, cb) {
transactionReceiptResolver.resolve(tx, cb)
@@ -368,11 +318,6 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
})
registry.put({api: eventsDecoder, name: 'eventsdecoder'})
- /*
- that proxy is used by appManager to broadcast new transaction event
- */
- const txListenerModule = new TxListenerModule(txlistener)
-
txlistener.startListening()
// TODO: There are still a lot of dep between editorpanel and filemanager
@@ -385,9 +330,13 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// ----------------- file manager ----------------------------
self._components.fileManager = new FileManager()
- var fileManager = self._components.fileManager
+ const fileManager = self._components.fileManager
registry.put({api: fileManager, name: 'filemanager'})
+ // ----------------- Network ----------------------------
+ const networkModule = new NetworkModule()
+ registry.put({api: networkModule, name: 'network'})
+
// ----------------- theme module ----------------------------
const themeModule = new ThemeModule()
registry.put({api: themeModule, name: 'themeModule'})
@@ -397,7 +346,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
registry.put({ api: self._components.editorpanel, name: 'editorpanel' })
// ----------------- Renderer -----------------
- var renderer = new Renderer()
+ const renderer = new Renderer()
registry.put({api: renderer, name: 'renderer'})
// ----------------- app manager ----------------------------
@@ -413,17 +362,18 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
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)
+
+ // ----------------- Vertical Icon ----------------------------
const verticalIconsComponent = new VerticalIconsComponent('swapPanel', appStore)
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: appManager.proxy(), name: 'pluginmanager'})
registry.put({api: verticalIconsApi, name: 'verticalicon'})
- pluginManagerComponent.setApp(appManager)
- pluginManagerComponent.setStore(appStore)
-
self._components.editorpanel.init()
self._components.fileManager.init()
@@ -469,16 +419,15 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
let sourceHighlighters = registry.get('editor').api.sourceHighlighters
appManager.init([
- this.api(),
landingPage.api(),
udapp.api(),
fileManager.api(),
sourceHighlighters.api(),
- txListenerModule.api(),
filePanel.api(),
// { profile: support.profile(), api: support },
settings.api(),
pluginManagerComponent.api(),
+ networkModule.api(),
themeModule.api()
])
@@ -496,8 +445,8 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
// The event listener needs to be registered as early as possible, because the
// parent will send the message upon the "load" event.
- var filesToLoad = null
- var loadFilesCallback = function (files) { filesToLoad = files } // will be replaced later
+ let filesToLoad = null
+ let loadFilesCallback = function (files) { filesToLoad = files } // will be replaced later
window.addEventListener('message', function (ev) {
if (typeof ev.data === typeof [] && ev.data[0] === 'loadFiles') {
@@ -515,7 +464,7 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
self.loadFiles(filesToLoad)
}
- var txLogger = new TxLogger() // eslint-disable-line
+ const txLogger = new TxLogger() // eslint-disable-line
txLogger.event.register('debuggingRequested', (hash) => {
if (!appStore.isActive('debugger')) appManager.activateOne('debugger')
debug.debugger().debug(hash)
@@ -547,9 +496,9 @@ Please make a backup of your contracts and start using http://remix.ethereum.org
}
udapp.resetAPI(transactionContextAPI)
- var queryParams = new QueryParams()
+ const queryParams = new QueryParams()
- var loadingFromGist = self.loadFromGist(queryParams.get())
+ const loadingFromGist = self.loadFromGist(queryParams.get())
if (!loadingFromGist) {
// insert ballot contract if there are no files to show
self._components.filesProviders['browser'].resolveDirectory('browser', (error, filesList) => {
diff --git a/src/app/components/plugin-manager-component.js b/src/app/components/plugin-manager-component.js
index 5be1d9a220..2213eceb3b 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, ApiFactory } from 'remix-plugin'
+import { Plugin, BaseApi } from 'remix-plugin'
const css = csjs`
.pluginSearch {
@@ -34,10 +34,21 @@ const css = csjs`
}
`
-class PluginManagerComponent extends ApiFactory {
+const profile = {
+ name: 'pluginManager',
+ displayName: 'Plugin manager',
+ methods: [],
+ events: [],
+ icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNzU1IDQ1M3EzNyAzOCAzNyA5MC41dC0zNyA5MC41bC00MDEgNDAwIDE1MCAxNTAtMTYwIDE2MHEtMTYzIDE2My0zODkuNSAxODYuNXQtNDExLjUtMTAwLjVsLTM2MiAzNjJoLTE4MXYtMTgxbDM2Mi0zNjJxLTEyNC0xODUtMTAwLjUtNDExLjV0MTg2LjUtMzg5LjVsMTYwLTE2MCAxNTAgMTUwIDQwMC00MDFxMzgtMzcgOTEtMzd0OTAgMzcgMzcgOTAuNS0zNyA5MC41bC00MDAgNDAxIDIzNCAyMzQgNDAxLTQwMHEzOC0zNyA5MS0zN3Q5MCAzN3oiLz48L3N2Zz4=',
+ description: 'Start/stop services, modules and plugins',
+ kind: 'settings',
+ location: 'swapPanel'
+}
+
+class PluginManagerComponent extends BaseApi {
constructor () {
- super()
+ super(profile)
this.event = new EventEmitter()
this.views = {
root: null,
@@ -47,19 +58,6 @@ class PluginManagerComponent extends ApiFactory {
this.filter = ''
}
- get profile () {
- return {
- displayName: 'plugin manager',
- name: 'pluginManager',
- methods: [],
- events: [],
- icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNzU1IDQ1M3EzNyAzOCAzNyA5MC41dC0zNyA5MC41bC00MDEgNDAwIDE1MCAxNTAtMTYwIDE2MHEtMTYzIDE2My0zODkuNSAxODYuNXQtNDExLjUtMTAwLjVsLTM2MiAzNjJoLTE4MXYtMTgxbDM2Mi0zNjJxLTEyNC0xODUtMTAwLjUtNDExLjV0MTg2LjUtMzg5LjVsMTYwLTE2MCAxNTAgMTUwIDQwMC00MDFxMzgtMzcgOTEtMzd0OTAgMzcgMzcgOTAuNS0zNyA5MC41bC00MDAgNDAxIDIzNCAyMzQgNDAxLTQwMHEzOC0zNyA5MS0zN3Q5MCAzN3oiLz48L3N2Zz4=',
- description: 'start/stop services, modules and plugins',
- kind: 'settings',
- location: 'swapPanel'
- }
- }
-
setApp (appManager) {
this.appManager = appManager
}
diff --git a/src/app/components/swap-panel-component.js b/src/app/components/swap-panel-component.js
index 3431fe2cc6..c6e15aae18 100644
--- a/src/app/components/swap-panel-component.js
+++ b/src/app/components/swap-panel-component.js
@@ -73,7 +73,7 @@ module.exports = SwapPanelComponent
const css = csjs`
.plugins {
- height : 100%;
+ height : 95%;
}
.plugItIn {
display : none;
diff --git a/src/app/components/vertical-icons-component.js b/src/app/components/vertical-icons-component.js
index 5d417b8bac..e85322e09a 100644
--- a/src/app/components/vertical-icons-component.js
+++ b/src/app/components/vertical-icons-component.js
@@ -1,6 +1,7 @@
var yo = require('yo-yo')
var csjs = require('csjs-inject')
var helper = require('../../lib/helper')
+let globalRegistry = require('../../global/registry')
const EventEmitter = require('events')
@@ -32,6 +33,11 @@ class VerticalIconComponent {
})
this.store.event.on('add', (api) => { })
this.store.event.on('remove', (api) => { })
+
+ let themeModule = globalRegistry.get('themeModule').api
+ themeModule.events.on('themeChanged', (type) => {
+ this.onThemeChanged(type)
+ })
}
stopListenOnStatus (api) {
@@ -56,8 +62,15 @@ class VerticalIconComponent {
* Add an icon to the map
* @param {ModuleProfile} profile The profile of the module
*/
- addIcon ({kind, name, icon, displayName}) {
- this.icons[name] = yo`
![${name}](${icon})
`
+ addIcon ({kind, name, icon, displayName, tooltip}) {
+ let title = (displayName || name)// + (tooltip ? tooltip : "")
+ this.icons[name] = yo`
+
+
![${name}](${icon})
+
`
this.iconKind[kind || 'other'].appendChild(this.icons[name])
}
@@ -69,7 +82,7 @@ class VerticalIconComponent {
setIconStatus (name, status) {
const el = this.icons[name]
if (!el) return
- let statusEl = el.querySelector('i')
+ let statusEl = el.querySelector('span')
if (statusEl) {
el.removeChild(statusEl)
}
@@ -77,7 +90,17 @@ class VerticalIconComponent {
let key = helper.checkSpecialChars(status.key) ? '' : status.key
let type = helper.checkSpecialChars(status.type) ? '' : status.type
let title = helper.checkSpecialChars(status.title) ? '' : status.title
- el.appendChild(yo``)
+ el.appendChild(yo``)
+
+ // el.classList = "" doesn't work on all browser use instead
+ var classList = el.classList
+ while (classList.length > 0) {
+ classList.remove(classList.item(0))
+ }
+
+ el.classList.add(`${css.icon}`)
+ el.classList.add('border')
+ el.classList.add(`border-${type}`)
}
}
@@ -89,22 +112,57 @@ class VerticalIconComponent {
if (this.icons[name]) this.iconKind[kind || 'other'].removeChild(this.icons[name])
}
- select (name) {
- let currentActive = this.view.querySelector(`.${css.active}`)
+ /**
+ * Remove active for the current activated icons
+ */
+ removeActive () {
+ // reset filters
+ const images = this.view.querySelectorAll(`.image`)
+ images.forEach(function (im) {
+ im.style.setProperty('filter', 'invert(0.5)')
+ })
+
+ // remove active
+ const currentActive = this.view.querySelector(`.${css.active}`)
if (currentActive) {
- let currentTitle = currentActive.getAttribute('title')
- currentActive.classList.toggle(`${css.active}`)
- if (currentTitle !== name) {
- let activate = this.view.querySelector(`[plugin="${name}"]`)
- if (activate) activate.classList.toggle(`${css.active}`)
- }
- } else {
- let activate = this.view.querySelector(`[plugin="${name}"]`)
- if (activate) activate.classList.toggle(`${css.active}`)
+ currentActive.classList.remove(css.active)
+ }
+ }
+
+ /**
+ * Add active for the new activated icon
+ * @param {string} name Name of profile of the module to activate
+ */
+ addActive (name) {
+ const themeType = globalRegistry.get('themeModule').api.currentTheme().quality
+ const invert = themeType === 'dark' ? 1 : 0
+ const nextActive = this.view.querySelector(`[plugin="${name}"]`)
+ if (nextActive) {
+ let image = nextActive.querySelector('.image')
+ nextActive.classList.add(css.active)
+ image.style.setProperty('filter', `invert(${invert})`)
}
+ }
+
+ /**
+ * Set an icon as active
+ * @param {string} name Name of profile of the module to activate
+ */
+ select (name) {
+ this.removeActive()
+ this.addActive(name)
this.events.emit('showContent', name)
}
+ onThemeChanged (themeType) {
+ const invert = themeType === 'dark' ? 1 : 0
+ const active = this.view.querySelector(`.${css.active}`)
+ if (active) {
+ let image = active.querySelector('.image')
+ image.style.setProperty('filter', `invert(${invert})`)
+ }
+ }
+
_iconClick (name) {
this.select(name)
}
@@ -173,31 +231,29 @@ const css = csjs`
margin-left: 10px;
margin-top: 15px;
}
- .icon {
+ .icon {
cursor: pointer;
margin-bottom: 12px;
width: 36px;
height: 36px;
padding: 3px;
position: relative;
+ border-radius: 8px;
}
.icon img {
width: 28px;
height: 28px;
padding: 4px;
+ filter: invert(0.5);
+ }
+ .image {
}
.icon svg {
width: 28px;
height: 28px;
padding: 4px;
}
- .icon.active {
- border: solid 3px hsla(229, 75%, 87%, 1);
- border-radius: 8px;
- padding-top: 1px;
- padding-left: 1px;
- }
- .icon[title='settings'] {
+ .icon[title='Settings'] {
position: absolute;
bottom: 0;
}
@@ -206,4 +262,15 @@ const css = csjs`
bottom: 0;
right: 0;
}
+ .statusWithBG
+ border-radius: 8px;
+ background-color: var(--danger);
+ color: var(--light);
+ font-size: 12px;
+ height: 15px;
+ text-align: center;
+ font-weight: bold;
+ padding-left: 5px;
+ padding-right: 5px;
+ }
`
diff --git a/src/app/debugger/debuggerUI/vmDebugger/CodeListView.js b/src/app/debugger/debuggerUI/vmDebugger/CodeListView.js
index 60562188e6..deb4545ca7 100644
--- a/src/app/debugger/debuggerUI/vmDebugger/CodeListView.js
+++ b/src/app/debugger/debuggerUI/vmDebugger/CodeListView.js
@@ -40,7 +40,8 @@ CodeListView.prototype.indexChanged = function (index) {
}
}
this.itemSelected = this.codeView.children[index]
- this.itemSelected.style.setProperty('background-color', 'var(--danger)')
+ this.itemSelected.style.setProperty('background-color', 'var(--info)')
+ this.itemSelected.style.setProperty('color', 'var(--light)')
this.itemSelected.setAttribute('selected', 'selected')
if (this.itemSelected.firstChild) {
this.itemSelected.firstChild.setAttribute('style', 'margin-left: 2px')
diff --git a/src/app/editor/SourceHighlighters.js b/src/app/editor/SourceHighlighters.js
index 85c69e2537..e2ea39bb76 100644
--- a/src/app/editor/SourceHighlighters.js
+++ b/src/app/editor/SourceHighlighters.js
@@ -1,24 +1,24 @@
'use strict'
const SourceHighlighter = require('./sourceHighlighter')
-import { ApiFactory } from 'remix-plugin'
+import { EditorApi } from 'remix-plugin'
-class SourceHighlighters extends ApiFactory {
+const profile = {
+ displayName: 'source highlighters',
+ name: 'editor',
+ description: 'service - highlight source code'
+}
+
+// EditorApi:
+// - methods: ['highlight', 'discardHighlight'],
+
+class SourceHighlighters extends EditorApi {
constructor () {
- super()
+ super(profile)
this.highlighters = {}
}
- get profile () {
- return {
- displayName: 'source highlighters',
- name: 'sourceHighlighters',
- methods: ['highlight', 'discardHighlight'],
- description: 'service - highlight source code'
- }
- }
-
highlight (lineColumnPos, filePath, hexColor) {
const { from } = this.currentRequest
try {
diff --git a/src/app/editor/editor.js b/src/app/editor/editor.js
index 748fd2b096..87ca2faa01 100644
--- a/src/app/editor/editor.js
+++ b/src/app/editor/editor.js
@@ -33,25 +33,6 @@ document.head.appendChild(yo`
.ace_gutter-cell.ace_breakpoint{
background-color: var(--secondary);
}
- .highlightreference {
- position:absolute;
- z-index:20;
- background-color: var(--primary);
- opacity: 0.6
- }
-
- .highlightreferenceline {
- position:absolute;
- z-index:20;
- background-color: var(--primary);
- opacity: 0.6
- }
-
- .highlightcode {
- position:absolute;
- z-index:20;
- background-color: var(--danger);
- }
`)
@@ -97,10 +78,14 @@ class Editor {
// Editor Setup
const el = yo``
this.editor = ace.edit(el)
+
ace.acequire('ace/ext/language_tools')
- // Unmap ctrl-t & ctrl-f
- this.editor.commands.bindKeys({ 'ctrl-t': null })
+ // Unmap ctrl-l & cmd-l
+ this.editor.commands.bindKeys({
+ 'ctrl-L': null,
+ 'Command-L': null
+ })
// shortcuts for "Ctrl-"" and "Ctrl+"" to increase/decrease font size of the editor
this.editor.commands.addCommand({
@@ -150,6 +135,13 @@ class Editor {
}
langTools.addCompleter(flowCompleter)
+ // zoom with Ctrl+wheel
+ window.addEventListener('wheel', (e) => {
+ if (e.ctrlKey && Math.abs(e.wheelY) > 5) {
+ this.editorFontSize(e.wheelY > 0 ? 1 : -1)
+ }
+ })
+
// EVENTS LISTENERS
// Gutter Mouse down
diff --git a/src/app/editor/sourceHighlighter.js b/src/app/editor/sourceHighlighter.js
index 9d026cda5d..1991e58f84 100644
--- a/src/app/editor/sourceHighlighter.js
+++ b/src/app/editor/sourceHighlighter.js
@@ -42,7 +42,7 @@ class SourceHighlighter {
this._deps.fileManager.switchFile(this.source)
}
- const backgoundClass = style || 'bg-info'
+ const backgoundClass = style || 'alert-info'
const css = csjs`
.highlightcode {
position:absolute;
diff --git a/src/app/execution/txLogger.js b/src/app/execution/txLogger.js
index 010fc46f7e..401c393caa 100644
--- a/src/app/execution/txLogger.js
+++ b/src/app/execution/txLogger.js
@@ -178,7 +178,7 @@ class TxLogger {
})
this._deps.txListener.event.register('newBlock', (block) => {
- if (!block.transactions.length) {
+ if (!block.transactions || block.transactions && !block.transactions.length) {
this.logEmptyBlock({ block: block })
}
})
diff --git a/src/app/files/browser-files-tree.js b/src/app/files/browser-files-tree.js
index 3c8eecf991..34df82b5db 100644
--- a/src/app/files/browser-files-tree.js
+++ b/src/app/files/browser-files-tree.js
@@ -2,12 +2,16 @@
var EventManager = require('../../lib/events')
-import { ApiFactory } from 'remix-plugin'
-
-class FilesTree extends ApiFactory {
+import { BaseApi } from 'remix-plugin'
+class FilesTree extends BaseApi {
constructor (name, storage) {
- super()
+ super({
+ name: name,
+ methods: ['get', 'set', 'remove'],
+ description:
+ 'service - read/write file to the `config` explorer without need of additionnal permission.'
+ })
this.event = new EventManager()
this.storage = storage
this.type = name
@@ -15,15 +19,6 @@ class FilesTree extends ApiFactory {
this.tree = {}
}
- get profile () {
- // TODO should make them promisable
- return {
- name: this.type,
- methods: ['get', 'set', 'remove'],
- description: 'service - read/write file to the `config` explorer without need of additionnal permission.'
- }
- }
-
exists (path, cb) {
cb(null, this._exists(path))
}
@@ -114,7 +109,11 @@ class FilesTree extends ApiFactory {
if (!this.storage.rename(unprefixedoldPath, unprefixednewPath)) {
return false
}
- this.event.trigger('fileRenamed', [this.type + '/' + unprefixedoldPath, this.type + '/' + unprefixednewPath, isFolder])
+ this.event.trigger('fileRenamed', [
+ this.type + '/' + unprefixedoldPath,
+ this.type + '/' + unprefixednewPath,
+ isFolder
+ ])
return true
}
return false
@@ -122,7 +121,7 @@ class FilesTree extends ApiFactory {
resolveDirectory (path, callback) {
if (path[0] === '/') path = path.substring(1)
- if (!path) return callback(null, { [this.type]: { } })
+ if (!path) return callback(null, { [this.type]: {} })
var tree = {}
path = this.removePrefix(path)
@@ -143,7 +142,6 @@ class FilesTree extends ApiFactory {
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 0ed8a3395d..b3b50868b3 100644
--- a/src/app/files/fileManager.js
+++ b/src/app/files/fileManager.js
@@ -1,20 +1,31 @@
'use strict'
-import { ApiFactory } from 'remix-plugin'
import yo from 'yo-yo'
const EventEmitter = require('events')
var globalRegistry = require('../../global/registry')
var CompilerImport = require('../compiler/compiler-imports')
var toaster = require('../ui/tooltip')
+import { FileSystemApi } from 'remix-plugin'
/*
attach to files event (removed renamed)
trigger: currentFileChanged
*/
-class FileManager extends ApiFactory {
+const profile = {
+ name: 'fileManager',
+ displayName: 'File manager',
+ description: 'Service - read/write to any files or folders, require giving permissions',
+ permission: true
+}
+
+// File System profile
+// - events: ['currentFileChanged']
+// - methods: ['getFolder', 'getCurrentFile', 'getFile', 'setFile']
+
+class FileManager extends FileSystemApi {
constructor (localRegistry) {
- super()
+ super(profile)
this.openedFiles = {} // list all opened files
this.events = new EventEmitter()
this._components = {}
@@ -42,18 +53,6 @@ class FileManager extends ApiFactory {
this._deps.localhostExplorer.event.register('closed', (event) => { this.removeTabsOf(this._deps.localhostExplorer) })
}
- get profile () {
- return {
- displayName: 'file manager',
- name: 'fileManager',
- methods: ['getFilesFromPath', 'getCurrentFile', 'getFile', 'setFile'],
- events: ['currentFileChanged'],
- description: 'service - read/write to any files or folders, require giving permissions',
- permission: true,
- icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4='
- }
- }
-
fileRenamedEvent (oldName, newName, isFolder) {
if (!isFolder) {
this._deps.config.set('currentFile', '')
@@ -223,7 +222,7 @@ class FileManager extends ApiFactory {
}
}
- getFilesFromPath (path) {
+ getFolder (path) {
// TODO : Change provider with promise
return new Promise((resolve, reject) => {
const provider = this.fileProviderOf(path)
diff --git a/src/app/files/remixd-handle.js b/src/app/files/remixd-handle.js
index f0cf7b8162..6787e2104d 100644
--- a/src/app/files/remixd-handle.js
+++ b/src/app/files/remixd-handle.js
@@ -1,5 +1,5 @@
-import { ApiFactory } from 'remix-plugin'
let globalRegistry = require('../../global/registry')
+import { BaseApi } from 'remix-plugin'
var yo = require('yo-yo')
var modalDialog = require('../ui/modaldialog')
@@ -18,23 +18,21 @@ var css = csjs`
}
`
-export class RemixdHandle extends ApiFactory {
+const profile = {
+ name: 'remixd',
+ methods: [],
+ events: [],
+ description: 'using Remixd daemon, allow to access file system',
+ kind: 'other'
+}
+
+export class RemixdHandle extends BaseApi {
constructor (fileSystemExplorer, locahostProvider) {
- super()
+ super(profile)
this.fileSystemExplorer = fileSystemExplorer
this.locahostProvider = locahostProvider
}
- get profile () {
- return {
- name: 'remixd',
- methods: [],
- events: [],
- description: 'using Remixd daemon, allow to access file system',
- kind: 'other'
- }
- }
-
deactivate () {
this.locahostProvider.close((error) => {
if (error) console.log(error)
diff --git a/src/app/panels/editor-panel.js b/src/app/panels/editor-panel.js
index 29640d36ba..95bd98443d 100644
--- a/src/app/panels/editor-panel.js
+++ b/src/app/panels/editor-panel.js
@@ -100,7 +100,8 @@ class EditorPanel {
self._components.contextView = contextView
self._components.terminal = new Terminal({
udapp: self._deps.udapp,
- compilers: {}
+ appStore: self.appStore,
+ appManager: self.appManager
},
{
getPosition: (event) => {
@@ -198,7 +199,7 @@ class EditorPanel {
self._adjustLayout('top', self.data._layout.top.offset)
document.addEventListener('keydown', (e) => {
- if (e.altKey && e.keyCode === 84) self.tabProxy.switchNextTab()
+ if (e.altKey && e.keyCode === 84) self.tabProxy.switchNextTab() // alt + t
})
return self._view.el
diff --git a/src/app/panels/file-panel.js b/src/app/panels/file-panel.js
index 5a42d28a2f..9bb56d9def 100644
--- a/src/app/panels/file-panel.js
+++ b/src/app/panels/file-panel.js
@@ -6,7 +6,7 @@ var { RemixdHandle } = require('../files/remixd-handle.js')
var globalRegistry = require('../../global/registry')
var css = require('./styles/file-panel-styles')
-import { ApiFactory } from 'remix-plugin'
+import { BaseApi } from 'remix-plugin'
var canUpload = window.File || window.FileReader || window.FileList || window.Blob
@@ -27,10 +27,21 @@ var canUpload = window.File || window.FileReader || window.FileList || window.Bl
- call fileProvider API
*/
-module.exports = class Filepanel extends ApiFactory {
+const profile = {
+ name: 'fileExplorers',
+ displayName: 'File explorers',
+ methods: [],
+ events: [],
+ icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4=',
+ description: ' - ',
+ kind: 'fileexplorer',
+ location: 'swapPanel'
+}
+
+module.exports = class Filepanel extends BaseApi {
constructor (localRegistry) {
- super()
+ super(profile)
var self = this
self._components = {}
self._components.registry = localRegistry || globalRegistry
@@ -132,18 +143,5 @@ module.exports = class Filepanel extends ApiFactory {
self.render = function render () { return element }
}
-
- get profile () {
- return {
- name: 'fileExplorers',
- displayName: 'file explorers',
- methods: [],
- events: [],
- icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjk2IDM4NHE0MCAwIDY4IDI4dDI4IDY4djEyMTZxMCA0MC0yOCA2OHQtNjggMjhoLTk2MHEtNDAgMC02OC0yOHQtMjgtNjh2LTI4OGgtNTQ0cS00MCAwLTY4LTI4dC0yOC02OHYtNjcycTAtNDAgMjAtODh0NDgtNzZsNDA4LTQwOHEyOC0yOCA3Ni00OHQ4OC0yMGg0MTZxNDAgMCA2OCAyOHQyOCA2OHYzMjhxNjgtNDAgMTI4LTQwaDQxNnptLTU0NCAyMTNsLTI5OSAyOTloMjk5di0yOTl6bS02NDAtMzg0bC0yOTkgMjk5aDI5OXYtMjk5em0xOTYgNjQ3bDMxNi0zMTZ2LTQxNmgtMzg0djQxNnEwIDQwLTI4IDY4dC02OCAyOGgtNDE2djY0MGg1MTJ2LTI1NnEwLTQwIDIwLTg4dDQ4LTc2em05NTYgODA0di0xMTUyaC0zODR2NDE2cTAgNDAtMjggNjh0LTY4IDI4aC00MTZ2NjQwaDg5NnoiLz48L3N2Zz4=',
- description: ' - ',
- kind: 'fileexplorer',
- location: 'swapPanel'
- }
- }
}
diff --git a/src/app/panels/styles/file-panel-styles.js b/src/app/panels/styles/file-panel-styles.js
index 4ccec900d7..6effb8a4f1 100644
--- a/src/app/panels/styles/file-panel-styles.js
+++ b/src/app/panels/styles/file-panel-styles.js
@@ -13,6 +13,8 @@ var css = csjs`
flex-direction : column;
position : relative;
width : 100%;
+ padding-left : 6px;
+ padding-top : 6px;
}
.gist {
padding : 10px;
@@ -50,7 +52,7 @@ var css = csjs`
.uploadFile label {
cursor : pointer;
}
- .treeviews {
+ .treeview {
overflow-y : auto;
}
.dialog {
diff --git a/src/app/panels/styles/terminal-styles.js b/src/app/panels/styles/terminal-styles.js
index 22a8a18bf4..8168747186 100644
--- a/src/app/panels/styles/terminal-styles.js
+++ b/src/app/panels/styles/terminal-styles.js
@@ -12,7 +12,6 @@ var css = csjs`
}
.bar {
display : flex;
- min-height : 3em;
z-index : 3;
}
.menu {
@@ -34,7 +33,6 @@ var css = csjs`
.toggleTerminal {
margin-right : 20px;
margin-left : 2px;
- margin-top : 2px;
font-size : 14px;
font-weight : bold;
cursor : pointer;
@@ -129,7 +127,6 @@ var css = csjs`
height : 65%;
}
.pendingTx {
- border : 1px solid var(--secondary);
border-radius : 50%;
margin-right : 30px;
min-width : 13px;
@@ -138,6 +135,7 @@ var css = csjs`
justify-content : center;
align-items : center;
font-size : 14px;
+ user-select : none;
}
.dragbarHorizontal {
position : absolute;
diff --git a/src/app/panels/tab-proxy.js b/src/app/panels/tab-proxy.js
index dbe0183ac4..7464b631c4 100644
--- a/src/app/panels/tab-proxy.js
+++ b/src/app/panels/tab-proxy.js
@@ -27,7 +27,7 @@ export class TabProxy {
this._view.filetabs.activateTab(file)
return
}
- this.addTab(file, () => {
+ this.addTab(file, '', () => {
this.fileManager.switchFile(file)
this.event.emit('switchFile', file)
},
@@ -39,7 +39,7 @@ export class TabProxy {
fileManager.events.on('fileRenamed', (oldName, newName) => {
this.removeTab(oldName)
- this.addTab(newName, () => {
+ this.addTab(newName, '', () => {
this.fileManager.switchFile(newName)
this.event.emit('switchFile', newName)
},
@@ -54,6 +54,7 @@ export class TabProxy {
if (profile.location === 'mainPanel') {
this.addTab(
name,
+ profile.displayName,
() => this.event.emit('switchApp', name),
() => {
this.event.emit('closeApp', name)
@@ -104,9 +105,13 @@ export class TabProxy {
this._view.filetabs.activateTab(name)
}
- addTab (name, switchTo, close, kind) {
+ addTab (name, title, switchTo, close, kind) {
+ if (this._handlers[name]) return
+
var slash = name.split('/')
- let title = name.indexOf('/') !== -1 ? slash[slash.length - 1] : name
+ if (!title) {
+ title = name.indexOf('/') !== -1 ? slash[slash.length - 1] : name
+ }
this._view.filetabs.addTab({
id: name,
title,
@@ -117,7 +122,7 @@ export class TabProxy {
}
removeTab (name) {
- this._view.filetabs.closeTab(name)
+ this._view.filetabs.removeTab(name)
delete this._handlers[name]
}
diff --git a/src/app/panels/terminal.js b/src/app/panels/terminal.js
index b881d88ab8..f9fb886208 100644
--- a/src/app/panels/terminal.js
+++ b/src/app/panels/terminal.js
@@ -17,6 +17,7 @@ var AutoCompletePopup = require('../ui/auto-complete-popup')
var csjs = require('csjs-inject')
var css = require('./styles/terminal-styles')
+import { BaseApi } from 'remix-plugin'
var packageV = require('../../../package.json')
@@ -26,8 +27,18 @@ function register (api) { KONSOLES.push(api) }
var ghostbar = yo``
-class Terminal {
+const profile = {
+ displayName: 'Terminal',
+ name: 'terminal',
+ methods: [],
+ events: [],
+ description: ' - ',
+ required: false
+}
+
+class Terminal extends BaseApi {
constructor (opts, api) {
+ super(profile)
var self = this
self.event = new EventManager()
self._api = api
@@ -62,12 +73,12 @@ class Terminal {
self.updateJournal({ type: 'select', value: label })
}
})
- self._components.autoCompletePopup = new AutoCompletePopup()
+ self._components.autoCompletePopup = new AutoCompletePopup(self._opts)
self._components.autoCompletePopup.event.register('handleSelect', function (input) {
let textList = self._view.input.innerText.split(' ')
textList.pop()
textList.push(input)
- self._view.input.innerText = `${textList}`.replace(/,/g, ' ')
+ self._view.input.innerText = textList
self._view.input.focus()
self.putCursor2End(self._view.input)
})
@@ -103,14 +114,18 @@ class Terminal {
self._jsSandboxContext = {}
self._jsSandboxRegistered = {}
+
+ self.externalApi = this.api()
+ self.externalApi.notifs = {'theme': ['switchTheme']}
+ opts.appManager.init([self.externalApi])
+ opts.appManager.activateRequestAndNotification(self.externalApi)
+
if (opts.shell) self._shell = opts.shell
register(self)
}
-
focus () {
if (this._view.input) this._view.input.focus()
}
-
render () {
var self = this
if (self._view.el) return self._view.el
@@ -127,7 +142,7 @@ class Terminal {
`
self._view.icon = yo`
`
+ class="btn btn-secondary btn-sm align-items-center ${css.toggleTerminal} fa fa-angle-double-down">`
self._view.dragbar = yo`
`
self._view.dropdown = self._components.dropdown.render()
@@ -136,7 +151,7 @@ class Terminal {
self._view.bar = yo`
${self._view.dragbar}
-