|
|
|
'use strict'
|
|
|
|
import { RunTab, makeUdapp } from './app/udapp'
|
|
|
|
import { RemixEngine } from './remixEngine'
|
|
|
|
import { RemixAppManager } from './remixAppManager'
|
|
|
|
import { ThemeModule } from './app/tabs/theme-module'
|
|
|
|
import { NetworkModule } from './app/tabs/network-module'
|
|
|
|
import { Web3ProviderModule } from './app/tabs/web3-provider'
|
|
|
|
import { SidePanel } from './app/components/side-panel'
|
|
|
|
import { HiddenPanel } from './app/components/hidden-panel'
|
|
|
|
import { VerticalIcons } from './app/components/vertical-icons'
|
|
|
|
import { LandingPage } from './app/ui/landing-page/landing-page'
|
|
|
|
import { MainPanel } from './app/components/main-panel'
|
|
|
|
import { PermissionHandlerPlugin } from './app/plugins/permission-handler-plugin'
|
|
|
|
import { AstWalker } from '@remix-project/remix-astwalker'
|
|
|
|
|
|
|
|
import { WalkthroughService } from './walkthroughService'
|
|
|
|
|
|
|
|
import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports, EditorContextListener, GistHandler } from '@remix-project/core-plugin'
|
|
|
|
|
|
|
|
import Registry from './app/state/registry'
|
|
|
|
import { ConfigPlugin } from './app/plugins/config'
|
|
|
|
import { StoragePlugin } from './app/plugins/storage'
|
|
|
|
import { Layout } from './app/panels/layout'
|
|
|
|
import { NotificationPlugin } from './app/plugins/notification'
|
|
|
|
import { Blockchain } from './blockchain/blockchain.js'
|
|
|
|
import { HardhatProvider } from './app/tabs/hardhat-provider'
|
|
|
|
|
|
|
|
const isElectron = require('is-electron')
|
|
|
|
|
|
|
|
const remixLib = require('@remix-project/remix-lib')
|
|
|
|
|
|
|
|
import { QueryParams } from '@remix-project/remix-lib'
|
|
|
|
|
|
|
|
const Storage = remixLib.Storage
|
|
|
|
const RemixDProvider = require('./app/files/remixDProvider')
|
|
|
|
const Config = require('./config')
|
|
|
|
|
|
|
|
const FileManager = require('./app/files/fileManager')
|
|
|
|
const FileProvider = require('./app/files/fileProvider')
|
|
|
|
const DGitProvider = require('./app/files/dgitProvider')
|
|
|
|
const WorkspaceFileProvider = require('./app/files/workspaceFileProvider')
|
|
|
|
|
|
|
|
const PluginManagerComponent = require('./app/components/plugin-manager-component')
|
|
|
|
|
|
|
|
const CompileTab = require('./app/tabs/compile-tab')
|
|
|
|
const SettingsTab = require('./app/tabs/settings-tab')
|
|
|
|
const AnalysisTab = require('./app/tabs/analysis-tab')
|
|
|
|
const { DebuggerTab } = require('./app/tabs/debugger-tab')
|
|
|
|
const TestTab = require('./app/tabs/test-tab')
|
|
|
|
const FilePanel = require('./app/panels/file-panel')
|
|
|
|
const Editor = require('./app/editor/editor')
|
|
|
|
const Terminal = require('./app/panels/terminal')
|
|
|
|
const { TabProxy } = require('./app/panels/tab-proxy.js')
|
|
|
|
|
|
|
|
class AppComponent {
|
|
|
|
constructor () {
|
|
|
|
this.appManager = new RemixAppManager({})
|
|
|
|
this.queryParams = new QueryParams()
|
|
|
|
this._components = {}
|
|
|
|
// setup storage
|
|
|
|
const configStorage = new Storage('config-v0.8:')
|
|
|
|
|
|
|
|
// load app config
|
|
|
|
const config = new Config(configStorage)
|
|
|
|
Registry.getInstance().put({ api: config, name: 'config' })
|
|
|
|
|
|
|
|
// load file system
|
|
|
|
this._components.filesProviders = {}
|
|
|
|
this._components.filesProviders.browser = new FileProvider('browser')
|
|
|
|
Registry.getInstance().put({
|
|
|
|
api: this._components.filesProviders.browser,
|
|
|
|
name: 'fileproviders/browser'
|
|
|
|
})
|
|
|
|
this._components.filesProviders.localhost = new RemixDProvider(
|
|
|
|
this.appManager
|
|
|
|
)
|
|
|
|
Registry.getInstance().put({
|
|
|
|
api: this._components.filesProviders.localhost,
|
|
|
|
name: 'fileproviders/localhost'
|
|
|
|
})
|
|
|
|
this._components.filesProviders.workspace = new WorkspaceFileProvider()
|
|
|
|
Registry.getInstance().put({
|
|
|
|
api: this._components.filesProviders.workspace,
|
|
|
|
name: 'fileproviders/workspace'
|
|
|
|
})
|
|
|
|
|
|
|
|
Registry.getInstance().put({
|
|
|
|
api: this._components.filesProviders,
|
|
|
|
name: 'fileproviders'
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async run () {
|
|
|
|
// APP_MANAGER
|
|
|
|
const appManager = this.appManager
|
|
|
|
const pluginLoader = this.appManager.pluginLoader
|
|
|
|
this.panels = {}
|
|
|
|
this.workspace = pluginLoader.get()
|
|
|
|
this.engine = new RemixEngine()
|
|
|
|
this.engine.register(appManager);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const matomoDomains = {
|
|
|
|
'remix-alpha.ethereum.org': 27,
|
|
|
|
'remix-beta.ethereum.org': 25,
|
|
|
|
'remix.ethereum.org': 23
|
|
|
|
}
|
|
|
|
this.showMatamo =
|
|
|
|
matomoDomains[window.location.hostname] &&
|
|
|
|
!Registry.getInstance()
|
|
|
|
.get('config')
|
|
|
|
.api.exists('settings/matomo-analytics')
|
|
|
|
this.walkthroughService = new WalkthroughService(
|
|
|
|
appManager,
|
|
|
|
this.showMatamo
|
|
|
|
)
|
|
|
|
|
|
|
|
const hosts = ['127.0.0.1:8080', '192.168.0.101:8080', 'localhost:8080']
|
|
|
|
// workaround for Electron support
|
|
|
|
if (!isElectron() && !hosts.includes(window.location.host)) {
|
|
|
|
// Oops! Accidentally trigger refresh or bookmark.
|
|
|
|
window.onbeforeunload = function () {
|
|
|
|
return 'Are you sure you want to leave?'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// SERVICES
|
|
|
|
// ----------------- gist service ---------------------------------
|
|
|
|
this.gistHandler = new GistHandler()
|
|
|
|
// ----------------- theme service ---------------------------------
|
|
|
|
this.themeModule = new ThemeModule()
|
|
|
|
Registry.getInstance().put({ api: this.themeModule, name: 'themeModule' })
|
|
|
|
|
|
|
|
// ----------------- editor service ----------------------------
|
|
|
|
const editor = new Editor() // wrapper around ace editor
|
|
|
|
Registry.getInstance().put({ api: editor, name: 'editor' })
|
|
|
|
editor.event.register('requiringToSaveCurrentfile', () =>
|
|
|
|
fileManager.saveCurrentFile()
|
|
|
|
)
|
|
|
|
|
|
|
|
// ----------------- fileManager service ----------------------------
|
|
|
|
const fileManager = new FileManager(editor, appManager)
|
|
|
|
Registry.getInstance().put({ api: fileManager, name: 'filemanager' })
|
|
|
|
// ----------------- dGit provider ---------------------------------
|
|
|
|
const dGitProvider = new DGitProvider()
|
|
|
|
|
|
|
|
// ----------------- Storage plugin ---------------------------------
|
|
|
|
const storagePlugin = new StoragePlugin()
|
|
|
|
|
|
|
|
//----- search
|
|
|
|
// const search = new SearchPlugin()
|
|
|
|
|
|
|
|
// ----------------- import content service ------------------------
|
|
|
|
const contentImport = new CompilerImports()
|
|
|
|
|
|
|
|
const blockchain = new Blockchain(Registry.getInstance().get('config').api)
|
|
|
|
|
|
|
|
// ----------------- compilation metadata generation service ---------
|
|
|
|
const compilerMetadataGenerator = new CompilerMetadata()
|
|
|
|
// ----------------- compilation result service (can keep track of compilation results) ----------------------------
|
|
|
|
const compilersArtefacts = new CompilerArtefacts() // store all the compilation results (key represent a compiler name)
|
|
|
|
Registry.getInstance().put({
|
|
|
|
api: compilersArtefacts,
|
|
|
|
name: 'compilersartefacts'
|
|
|
|
})
|
|
|
|
|
|
|
|
// service which fetch contract artifacts from sourve-verify, put artifacts in remix and compile it
|
|
|
|
const fetchAndCompile = new FetchAndCompile()
|
|
|
|
// ----------------- network service (resolve network id / name) -----
|
|
|
|
const networkModule = new NetworkModule(blockchain)
|
|
|
|
// ----------------- represent the current selected web3 provider ----
|
|
|
|
const web3Provider = new Web3ProviderModule(blockchain)
|
|
|
|
const hardhatProvider = new HardhatProvider(blockchain)
|
|
|
|
// ----------------- convert offset to line/column service -----------
|
|
|
|
const offsetToLineColumnConverter = new OffsetToLineColumnConverter()
|
|
|
|
Registry.getInstance().put({
|
|
|
|
api: offsetToLineColumnConverter,
|
|
|
|
name: 'offsettolinecolumnconverter'
|
|
|
|
})
|
|
|
|
|
|
|
|
// -------------------Terminal----------------------------------------
|
|
|
|
makeUdapp(blockchain, compilersArtefacts, domEl => terminal.logHtml(domEl))
|
|
|
|
const terminal = new Terminal(
|
|
|
|
{ appManager, blockchain },
|
|
|
|
{
|
|
|
|
getPosition: event => {
|
|
|
|
const limitUp = 36
|
|
|
|
const limitDown = 20
|
|
|
|
const height = window.innerHeight
|
|
|
|
let newpos = event.pageY < limitUp ? limitUp : event.pageY
|
|
|
|
newpos = newpos < height - limitDown ? newpos : height - limitDown
|
|
|
|
return height - newpos
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
const contextualListener = new EditorContextListener(new AstWalker())
|
|
|
|
|
|
|
|
this.notification = new NotificationPlugin()
|
|
|
|
|
|
|
|
const configPlugin = new ConfigPlugin()
|
|
|
|
this.layout = new Layout()
|
|
|
|
|
|
|
|
const permissionHandler = new PermissionHandlerPlugin()
|
|
|
|
|
|
|
|
this.engine.register([
|
|
|
|
permissionHandler,
|
|
|
|
this.layout,
|
|
|
|
this.notification,
|
|
|
|
this.gistHandler,
|
|
|
|
configPlugin,
|
|
|
|
blockchain,
|
|
|
|
contentImport,
|
|
|
|
this.themeModule,
|
|
|
|
editor,
|
|
|
|
fileManager,
|
|
|
|
compilerMetadataGenerator,
|
|
|
|
compilersArtefacts,
|
|
|
|
networkModule,
|
|
|
|
offsetToLineColumnConverter,
|
|
|
|
contextualListener,
|
|
|
|
terminal,
|
|
|
|
web3Provider,
|
|
|
|
fetchAndCompile,
|
|
|
|
dGitProvider,
|
|
|
|
storagePlugin,
|
|
|
|
hardhatProvider,
|
|
|
|
this.walkthroughService,
|
|
|
|
])
|
|
|
|
|
|
|
|
// LAYOUT & SYSTEM VIEWS
|
|
|
|
const appPanel = new MainPanel()
|
|
|
|
Registry.getInstance().put({ api: this.mainview, name: 'mainview' })
|
|
|
|
const tabProxy = new TabProxy(fileManager, editor)
|
|
|
|
this.engine.register([appPanel, tabProxy])
|
|
|
|
|
|
|
|
// those views depend on app_manager
|
|
|
|
this.menuicons = new VerticalIcons()
|
|
|
|
this.sidePanel = new SidePanel()
|
|
|
|
this.hiddenPanel = new HiddenPanel()
|
|
|
|
|
|
|
|
const pluginManagerComponent = new PluginManagerComponent(
|
|
|
|
appManager,
|
|
|
|
this.engine
|
|
|
|
)
|
|
|
|
const filePanel = new FilePanel(appManager)
|
|
|
|
const landingPage = new LandingPage(
|
|
|
|
appManager,
|
|
|
|
this.menuicons,
|
|
|
|
fileManager,
|
|
|
|
filePanel,
|
|
|
|
contentImport
|
|
|
|
)
|
|
|
|
this.settings = new SettingsTab(
|
|
|
|
Registry.getInstance().get('config').api,
|
|
|
|
editor,
|
|
|
|
appManager
|
|
|
|
)
|
|
|
|
|
|
|
|
this.engine.register([
|
|
|
|
this.menuicons,
|
|
|
|
landingPage,
|
|
|
|
this.hiddenPanel,
|
|
|
|
this.sidePanel,
|
|
|
|
filePanel,
|
|
|
|
pluginManagerComponent,
|
|
|
|
this.settings
|
|
|
|
])
|
|
|
|
|
|
|
|
// CONTENT VIEWS & DEFAULT PLUGINS
|
|
|
|
const compileTab = new CompileTab(
|
|
|
|
Registry.getInstance().get('config').api,
|
|
|
|
Registry.getInstance().get('filemanager').api
|
|
|
|
)
|
|
|
|
const run = new RunTab(
|
|
|
|
blockchain,
|
|
|
|
Registry.getInstance().get('config').api,
|
|
|
|
Registry.getInstance().get('filemanager').api,
|
|
|
|
Registry.getInstance().get('editor').api,
|
|
|
|
filePanel,
|
|
|
|
Registry.getInstance().get('compilersartefacts').api,
|
|
|
|
networkModule,
|
|
|
|
Registry.getInstance().get('fileproviders/browser').api
|
|
|
|
)
|
|
|
|
const analysis = new AnalysisTab()
|
|
|
|
const debug = new DebuggerTab()
|
|
|
|
const test = new TestTab(
|
|
|
|
Registry.getInstance().get('filemanager').api,
|
|
|
|
Registry.getInstance().get('offsettolinecolumnconverter').api,
|
|
|
|
filePanel,
|
|
|
|
compileTab,
|
|
|
|
appManager,
|
|
|
|
contentImport
|
|
|
|
)
|
|
|
|
|
|
|
|
this.engine.register([
|
|
|
|
compileTab,
|
|
|
|
run,
|
|
|
|
debug,
|
|
|
|
analysis,
|
|
|
|
test,
|
|
|
|
filePanel.remixdHandle,
|
|
|
|
filePanel.gitHandle,
|
|
|
|
filePanel.hardhatHandle,
|
|
|
|
filePanel.slitherHandle
|
|
|
|
])
|
|
|
|
|
|
|
|
this.layout.panels = {
|
|
|
|
tabs: { plugin: tabProxy, active: true },
|
|
|
|
editor: { plugin: editor, active: true },
|
|
|
|
main: { plugin: appPanel, active: false },
|
|
|
|
terminal: { plugin: terminal, active: true, minimized: false }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async activate () {
|
|
|
|
const queryParams = new QueryParams()
|
|
|
|
const params = queryParams.get()
|
|
|
|
|
|
|
|
if (isElectron()) {
|
|
|
|
this.appManager.activatePlugin('remixd')
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
this.engine.register(await this.appManager.registeredPlugins())
|
|
|
|
} catch (e) {
|
|
|
|
console.log("couldn't register iframe plugins", e.message)
|
|
|
|
}
|
|
|
|
await this.appManager.activatePlugin(['layout'])
|
|
|
|
await this.appManager.activatePlugin(['notification'])
|
|
|
|
await this.appManager.activatePlugin(['editor'])
|
|
|
|
await this.appManager.activatePlugin(['permissionhandler', 'theme', 'fileManager', 'compilerMetadata', 'compilerArtefacts', 'network', 'web3Provider', 'offsetToLineColumnConverter'])
|
|
|
|
await this.appManager.activatePlugin(['mainPanel', 'menuicons', 'tabs'])
|
|
|
|
await this.appManager.activatePlugin(['sidePanel']) // activating host plugin separately
|
|
|
|
await this.appManager.activatePlugin(['home'])
|
|
|
|
await this.appManager.activatePlugin(['settings', 'config'])
|
|
|
|
await this.appManager.activatePlugin(['hiddenPanel', 'pluginManager', 'contextualListener', 'terminal', 'blockchain', 'fetchAndCompile', 'contentImport', 'gistHandler'])
|
|
|
|
await this.appManager.activatePlugin(['settings'])
|
|
|
|
await this.appManager.activatePlugin(['walkthrough','storage'])
|
|
|
|
|
|
|
|
this.appManager.on(
|
|
|
|
'filePanel',
|
|
|
|
'workspaceInitializationCompleted',
|
|
|
|
async () => {
|
|
|
|
await this.appManager.registerContextMenuItems()
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
await this.appManager.activatePlugin(['filePanel'])
|
|
|
|
// Set workspace after initial activation
|
|
|
|
this.appManager.on('editor', 'editorMounted', () => {
|
|
|
|
if (Array.isArray(this.workspace)) {
|
|
|
|
this.appManager
|
|
|
|
.activatePlugin(this.workspace)
|
|
|
|
.then(async () => {
|
|
|
|
try {
|
|
|
|
if (params.deactivate) {
|
|
|
|
await this.appManager.deactivatePlugin(
|
|
|
|
params.deactivate.split(',')
|
|
|
|
)
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e)
|
|
|
|
}
|
|
|
|
if (params.code && (!params.activate || params.activate==='solidity')) {
|
|
|
|
// if code is given in url we focus on solidity plugin
|
|
|
|
this.menuicons.select('solidity')
|
|
|
|
} else {
|
|
|
|
// If plugins are loaded from the URL params, we focus on the last one.
|
|
|
|
if (
|
|
|
|
this.appManager.pluginLoader.current === 'queryParams' &&
|
|
|
|
this.workspace.length > 0
|
|
|
|
) { this.menuicons.select(this.workspace[this.workspace.length - 1]) }
|
|
|
|
}
|
|
|
|
|
|
|
|
if (params.call) {
|
|
|
|
const callDetails = params.call.split('//')
|
|
|
|
if (callDetails.length > 1) {
|
|
|
|
this.appManager.call('notification', 'toast', `initiating ${callDetails[0]} ...`)
|
|
|
|
// @todo(remove the timeout when activatePlugin is on 0.3.0)
|
|
|
|
this.appManager.call(...callDetails).catch(console.error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch(console.error)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
// activate solidity plugin
|
|
|
|
this.appManager.activatePlugin(['solidity', 'udapp'])
|
|
|
|
// Load and start the service who manager layout and frame
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default AppComponent
|