@ -1,17 +1,12 @@
/* global Worker */
var yo = require ( 'yo-yo' )
var csjs = require ( 'csjs-inject' )
var minixhr = require ( 'minixhr' )
var remixLib = require ( 'remix-lib' )
const defaultPlugins = require ( '../plugin/plugins' )
var globalRegistry = require ( '../../global/registry' )
var QueryParams = require ( '../../lib/query-params' )
var helper = require ( '../../lib/helper' )
var modal = require ( '../ui/modal-dialog-custom' )
var tooltip = require ( '../ui/tooltip' )
var copyToClipboard = require ( '../ui/copy-to-clipboard' )
var styleGuide = require ( '../ui/styles-guide/theme-chooser' )
var styles = styleGuide . chooser ( )
var Storage = remixLib . Storage
var EventManager = remixLib . EventManager
@ -31,33 +26,19 @@ module.exports = class SettingsTab {
}
self . _view = { /* eslint-disable */
el : null ,
optionVM : null , personal : null , optimize : null , warnPersonalMode : null ,
optionVM : null , personal : null , warnPersonalMode : null ,
pluginInput : null , versionSelector : null , version : null ,
theme : { dark : null , light : null } ,
plugins : { } ,
config : {
solidity : null , general : null , themes : null ,
plugin : null , remixd : null , localremixd : null
general : null , themes : null ,
plugin : null
}
} /* eslint-enable */
self . data = {
allversions : null ,
selectedVersion : null ,
baseurl : 'https://solc-bin.ethereum.org/bin'
}
self . data = { }
self . event = new EventManager ( )
self . _components . queryParams = new QueryParams ( )
self . _components . themeStorage = new Storage ( 'style:' )
self . data . optimize = ! ! self . _components . queryParams . get ( ) . optimize
self . _components . queryParams . update ( { optimize : self . data . optimize } )
self . _deps . compiler . setOptimize ( self . data . optimize )
self . data . currentTheme = self . _components . themeStorage . get ( 'theme' ) || 'light'
self . _deps . compiler . event . register ( 'compilerLoaded' , ( version ) => self . setVersionText ( version ) )
self . fetchAllVersion ( ( allversions , selectedVersion ) => {
self . data . allversions = allversions
self . data . selectedVersion = selectedVersion
if ( self . _view . versionSelector ) self . _updateVersionSelector ( )
} )
}
render ( ) {
const self = this
@ -75,8 +56,6 @@ module.exports = class SettingsTab {
if ( self . _deps . config . get ( 'settings/always-use-vm' ) ) self . _view . optionVM . setAttribute ( 'checked' , '' )
self . _view . personal = yo ` <input onchange= ${ onchangePersonal } id="personal" type="checkbox"> `
if ( self . _deps . config . get ( 'settings/personal-mode' ) ) self . _view . personal . setAttribute ( 'checked' , '' )
self . _view . optimize = yo ` <input onchange= ${ onchangeOptimize } id="optimize" type="checkbox"> `
if ( self . data . optimize ) self . _view . optimize . setAttribute ( 'checked' , '' )
var warnText = ` Transaction sent over Web3 will use the web3.personal API - be sure the endpoint is opened before enabling it.
This mode allows to provide the passphrase in the Remix interface without having to unlock the account .
Although this is very convenient , you should completely trust the backend you are connected to ( Geth , Parity , ... ) .
@ -84,23 +63,11 @@ module.exports = class SettingsTab {
Remix never persist any passphrase . ` .split(' \n ').map(s => s.trim()).join(' ')
self . _view . warnPersonalMode = yo ` <i title= ${ warnText } class=" ${ css . icon } fa fa-exclamation-triangle" aria-hidden="true"></i> `
self . _view . pluginInput = yo ` <textarea rows="4" cols="70" id="plugininput" type="text" class=" ${ css . pluginTextArea } " ></textarea> `
self . _view . versionSelector = yo `
< select onchange = $ { onchangeLoadVersion } class = "${css.select}" id = "versionSelector" disabled >
< option disabled selected > Select new compiler version < / o p t i o n >
< / s e l e c t > `
if ( self . data . allversions && self . data . selectedVersion ) self . _updateVersionSelector ( )
self . _view . version = yo ` <span id="version"></span> `
self . _view . theme . light = yo ` <input onchange= ${ onswitch2lightTheme } class=" ${ css . col1 } " name="theme" id="themeLight" type="radio"> `
self . _view . theme . dark = yo ` <input onchange= ${ onswitch2darkTheme } class=" ${ css . col1 } " name="theme" id="themeDark" type="radio"> `
self . _view . theme [ self . data . currentTheme ] . setAttribute ( 'checked' , 'checked' )
self . _view . config . solidity = yo `
< div class = "${css.info}" >
< div class = $ { css . title } > Solidity version < / d i v >
< span > Current version : < / s p a n > $ { s e l f . _ v i e w . v e r s i o n }
< div class = "${css.crow}" >
$ { self . _view . versionSelector }
< / d i v >
< / d i v > `
self . _view . config . general = yo `
< div class = "${css.info}" >
< div class = $ { css . title } > General settings < / d i v >
@ -112,10 +79,6 @@ module.exports = class SettingsTab {
< div > < input id = "editorWrap" type = "checkbox" onchange = $ { function ( ) { self . _deps . editor . resize ( this . checked ) } } > < / d i v >
< span class = "${css.checkboxText}" > Text Wrap < / s p a n >
< / d i v >
< div class = "${css.crow}" >
< div > $ { self . _view . optimize } < / d i v >
< span class = "${css.checkboxText}" > Enable Optimization < / s p a n >
< / d i v >
< div class = "${css.crow}" >
< div > $ { self . _view . personal } > < / d i v >
< span class = "${css.checkboxText}" > Enable Personal Mode $ { self . _view . warnPersonalMode } > < / s p a n >
@ -146,67 +109,75 @@ module.exports = class SettingsTab {
< label for = "themeDark" > Dark Theme < / l a b e l >
< / d i v >
< / d i v > `
self . _view . config . plugins = yo ` <div></div> `
self . _view . config . plugin = yo `
< div class = "${css.info}" >
< div class = $ { css . title } > Plugin < / d i v >
< div class = "${css.crowNoFlex}" >
< input onclick = $ { ( ) => { onLoadPlugin ( 'oraclize' ) } } type = "button" value = "Oraclize" class = "${css.pluginLoad}" >
< input onclick = $ { ( ) => { onLoadPlugin ( 'etherscan-general' ) } } type = "button" value = "Etherscan-general" class = "${css.pluginLoad}" >
< div > Load plugin from JSON description : < / d i v >
$ { self . _view . pluginInput }
< input onclick = $ { onloadPluginJson } type = "button" value = "Load" class = "${css.pluginLoad}" >
< / d i v >
< / d i v > `
self . _view . config . remixd = yo `
< div class = "${css.info}" >
< div class = $ { css . title } > Remixd < / d i v >
< div class = "${css.crow}" >
Remixd is a tool which allow Remix IDE to access files located in your local computer .
it can also be used to setup a development environment .
< input onclick = $ { onloadPluginJson } type = "button" value = "Load" class = "${css.initPlugin}" >
$ { self . _view . config . plugins }
< / d i v >
< div class = "${css.crow}" > More infos : < / d i v >
< div class = "${css.crow}" > < a target = "_blank" href = "https://github.com/ethereum/remixd" > https : //github.com/ethereum/remixd</a></div>
< div class = "${css.crow}" > < a target = "_blank" href = "https://remix.readthedocs.io/en/latest/tutorial_remixd_filesystem" > http : //remix.readthedocs.io/en/latest/tutorial_remixd_filesystem.html</a></div>
< div class = "${css.crow}" > Installation : < pre class = $ { css . remixdinstallation } > npm install remixd - g < / p r e > < / d i v >
< / d i v > `
self . _view . config . localremixd = yo `
< div class = "${css.info}" >
< div class = $ { css . title } > Running Remix locally < / d i v >
< div class = "${css.crow}" >
as a NPM module :
< / d i v >
< a target = "_blank" href = "https://www.npmjs.com/package/remix-ide" > https : //www.npmjs.com/package/remix-ide</a>
< pre class = $ { css . remixdinstallation } > npm install remix - ide - g < / p r e >
< div class = "${css.crow}" >
as an electron app :
< / d i v >
< a target = "_blank" href = "https://github.com/horizon-games/remix-app" > https : //github.com/horizon-games/remix-app</a>
< / d i v > `
self . _view . el = yo `
< div class = "${css.settingsTabView} " id = "settingsView" >
$ { self . _view . config . solidity }
< div class = "${css.settingsTabView}" id = "settingsView" >
$ { self . _view . config . general }
$ { self . _view . config . plugin }
$ { self . _view . gistToken }
$ { self . _view . config . themes }
$ { self . _view . config . plugin }
$ { self . _view . config . remixd }
$ { self . _view . config . localremixd }
< / d i v > `
function onchangeOption ( event ) {
self . _deps . config . set ( 'settings/always-use-vm' , ! self . _deps . config . get ( 'settings/always-use-vm' ) )
function loadPlugins ( plugins , opt ) {
for ( var k in plugins ) {
var plugin = plugins [ k ]
if ( ! self . _view . plugins [ plugin . title ] ) self . _view . plugins [ plugin . title ] = { }
self . _view . plugins [ plugin . title ] . json = plugin
self . _view . plugins [ plugin . title ] . el = yo ` <div title= ${ plugin . title } class=" ${ css . pluginLoad } ">
< div class = "${css.aPlugin}" onclick = $ { ( ) => { onLoadPlugin ( plugin . title ) } } > $ { plugin . title } < / d i v >
$ { opt . removable ? yo ` <span class=" ${ css . removePlugin } " onclick= ${ ( ) => { onRemovePlugin ( plugin . title ) } }><i class="fa fa-close"></i></span> ` : yo ` <span></span> ` }
< / d i v > `
self . _view . config . plugins . appendChild ( self . _view . plugins [ plugin . title ] . el )
}
}
function getSavedPlugin ( ) {
var savedPlugin = self . _deps . config . get ( 'settings/plugins-list' )
return savedPlugin ? JSON . parse ( savedPlugin ) : { }
}
function setSavedPlugin ( savedPlugins ) {
self . _deps . config . set ( 'settings/plugins-list' , JSON . stringify ( savedPlugins ) )
}
loadPlugins ( defaultPlugins , { removable : false } )
loadPlugins ( getSavedPlugin ( ) , { removable : true } )
function onLoadPlugin ( name ) {
// @TODO: BAD! REFACTOR: no module should trigger events of another modules emitter
self . _deps . righthandpanel . event . trigger ( 'plugin-name-loadRequest' , [ name ] )
self . event . trigger ( 'plugin-loadRequest' , [ self . _view . plugins [ name ] . json ] )
}
function onRemovePlugin ( name ) {
var savedPlugin = getSavedPlugin ( )
delete savedPlugin [ name ]
setSavedPlugin ( savedPlugin )
if ( self . _view . plugins [ name ] ) {
self . _view . plugins [ name ] . el . parentNode . removeChild ( self . _view . plugins [ name ] . el )
delete self . _view . plugins [ name ]
}
}
function onloadPluginJson ( event ) {
try {
var json = JSON . parse ( self . _view . pluginInput . value )
} catch ( e ) {
return modal . alert ( 'cannot parse the plugin definition to JSON' )
return tooltip ( 'cannot parse the plugin definition to JSON' )
}
var savedPlugin = getSavedPlugin ( )
if ( self . _view . plugins [ json . title ] ) return tooltip ( 'Plugin already loaded' )
savedPlugin [ json . title ] = json
setSavedPlugin ( savedPlugin )
loadPlugins ( [ json ] , { removable : true } )
}
// @TODO: BAD! REFACTOR: no module should trigger events of another modules emitter
self . _deps . righthandpanel . event . trigger ( 'plugin-loadRequest' , [ json ] )
function onchangeOption ( event ) {
self . _deps . config . set ( 'settings/always-use-vm' , ! self . _deps . config . get ( 'settings/always-use-vm' ) )
}
function onswitch2darkTheme ( event ) {
styleGuide . switchTheme ( 'dark' )
@ -216,79 +187,11 @@ module.exports = class SettingsTab {
styleGuide . switchTheme ( 'light' )
window . location . reload ( )
}
function onchangeOptimize ( event ) {
self . data . optimize = ! ! self . _view . optimize . checked
self . _components . queryParams . update ( { optimize : self . data . optimize } )
self . _deps . compiler . setOptimize ( self . data . optimize )
self . _deps . app . runCompiler ( )
}
function onchangeLoadVersion ( event ) {
self . data . selectedVersion = self . _view . versionSelector . value
self . _updateVersionSelector ( )
}
function onchangePersonal ( event ) {
self . _deps . config . set ( 'settings/personal-mode' , ! self . _deps . config . get ( 'settings/personal-mode' ) )
}
return self . _view . el
}
setVersionText ( text ) {
const self = this
self . data . version = text
if ( self . _view . version ) self . _view . version . innerText = text
}
_updateVersionSelector ( ) {
const self = this
self . _view . versionSelector . innerHTML = ''
self . _view . versionSelector . appendChild ( yo ` <option disabled selected>Select new compiler version</option> ` )
self . data . allversions . forEach ( build => self . _view . versionSelector . appendChild ( yo ` <option value= ${ build . path } > ${ build . longVersion } </option> ` ) )
self . _view . versionSelector . removeAttribute ( 'disabled' )
self . _components . queryParams . update ( { version : self . data . selectedVersion } )
var url
if ( self . data . selectedVersion === 'builtin' ) {
var location = window . document . location
location = location . protocol + '//' + location . host + '/' + location . pathname
if ( location . endsWith ( 'index.html' ) ) location = location . substring ( 0 , location . length - 10 )
if ( ! location . endsWith ( '/' ) ) location += '/'
url = location + 'soljson.js'
} else {
if ( self . data . selectedVersion . indexOf ( 'soljson' ) !== 0 || helper . checkSpecialChars ( self . data . selectedVersion ) ) {
return console . log ( 'loading ' + self . data . selectedVersion + ' not allowed' )
}
url = ` ${ self . data . baseurl } / ${ self . data . selectedVersion } `
}
var isFirefox = typeof InstallTrigger !== 'undefined'
if ( document . location . protocol !== 'file:' && Worker !== undefined && isFirefox ) {
// Workers cannot load js on "file:"-URLs and we get a
// "Uncaught RangeError: Maximum call stack size exceeded" error on Chromium,
// resort to non-worker version in that case.
self . _deps . compiler . loadVersion ( true , url )
self . setVersionText ( '(loading using worker)' )
} else {
self . _deps . compiler . loadVersion ( false , url )
self . setVersionText ( '(loading)' )
}
}
fetchAllVersion ( callback ) {
var self = this
minixhr ( ` ${ self . data . baseurl } /list.json ` , function ( json , event ) {
// @TODO: optimise and cache results to improve app loading times
var allversions , selectedVersion
if ( event . type !== 'error' ) {
try {
const data = JSON . parse ( json )
allversions = data . builds . slice ( ) . reverse ( )
selectedVersion = data . releases [ data . latestRelease ]
if ( self . _components . queryParams . get ( ) . version ) selectedVersion = self . _components . queryParams . get ( ) . version
} catch ( e ) {
tooltip ( 'Cannot load compiler version list. It might have been blocked by an advertisement blocker. Please try deactivating any of them from this page and reload.' )
}
} else {
allversions = [ { path : 'builtin' , longVersion : 'latest local version' } ]
selectedVersion = 'builtin'
}
callback ( allversions , selectedVersion )
} )
}
}
const css = csjs `
@ -297,7 +200,7 @@ const css = csjs`
display : flex ;
}
. info {
$ { styles . rightPanel . settingsTab . box _SolidityVersionInfo }
$ { styles . rightPanel . settingsTab . box _SolidityVersionInfo } ;
margin - bottom : 1 em ;
word - break : break - word ;
}
@ -327,11 +230,6 @@ const css = csjs`
padding : . 5 em ;
font - weight : bold ;
}
. select {
font - weight : bold ;
margin - top : 1 em ;
$ { styles . rightPanel . settingsTab . dropdown _SelectCompiler } ;
}
. heading {
margin - bottom : 0 ;
}
@ -356,18 +254,48 @@ const css = csjs`
width : inherit ;
display : inline - block ;
}
. initPlugin {
vertical - align : top ;
$ { styles . rightPanel . settingsTab . button _initPlugin } ;
width : inherit ;
display : block ;
max - height : inherit ;
padding : 7 px ;
}
. removePlugin {
cursor : pointer ;
}
i . warnIt {
color : $ { styles . appProperties . warningText _Color } ;
}
. icon {
margin - right : . 5 em ;
}
. remixdinstallation {
padding : 3 px ;
border - radius : 2 px ;
margin - left : 5 px ;
}
. savegisttoken {
margin - left : 5 px ;
}
. aPlugin {
display : inline - block ;
padding - left : 10 px ;
padding - top : 4 px ;
padding - bottom : 6 px ;
max - width : 100 px ;
text - overflow : ellipsis ;
overflow : hidden ;
white - space : nowrap ;
vertical - align : middle ;
}
. pluginLoad {
vertical - align : top ;
max - height : inherit ;
margin : 2 px ;
}
. removePlugin {
padding - left : 7 px ;
padding - right : 7 px ;
border - left : 2 px solid $ { styles . appProperties . primary _BackgroundColor } ;
margin - left : 10 px ;
}
`