Unverified Commit 95039cb3 authored by EthereumRemix's avatar EthereumRemix Committed by GitHub

Merge branch 'master' into ImproveAnnotation

parents d283d9d7 090d0eee
...@@ -15,21 +15,15 @@ class addAtAddressInstance extends EventEmitter { ...@@ -15,21 +15,15 @@ class addAtAddressInstance extends EventEmitter {
function addInstance (browser: NightwatchBrowser, address: string, isValidFormat: boolean, isValidChecksum: boolean, callback: VoidFunction) { function addInstance (browser: NightwatchBrowser, address: string, isValidFormat: boolean, isValidChecksum: boolean, callback: VoidFunction) {
browser.clickLaunchIcon('udapp').clearValue('.ataddressinput').setValue('.ataddressinput', address, function () { browser.clickLaunchIcon('udapp').clearValue('.ataddressinput').setValue('.ataddressinput', address, function () {
browser.click('button[id^="runAndDeployAtAdressButton"]') if (!isValidFormat || !isValidChecksum) browser.assert.elementPresent('button[id^="runAndDeployAtAdressButton"]:disabled')
.execute(function () { else {
const ret = document.querySelector('div[class^="modal-body"] div').innerHTML browser.click('button[id^="runAndDeployAtAdressButton"]')
const modal = document.querySelector('#modal-footer-ok') as HTMLElement .execute(function () {
const modal = document.querySelector('#modal-footer-ok') as HTMLElement
modal.click() modal.click()
return ret })
}, [], function (result) { }
if (!isValidFormat) { callback()
browser.assert.equal(result.value, 'Invalid address.')
} else if (!isValidChecksum) {
browser.assert.equal(result.value, 'Invalid checksum address.')
}
callback()
})
}) })
} }
......
...@@ -32,6 +32,22 @@ ...@@ -32,6 +32,22 @@
<link rel="icon" type="x-icon" href="assets/img/icon.png"> <link rel="icon" type="x-icon" href="assets/img/icon.png">
<script src="assets/js/browserfs.min.js"></script> <script src="assets/js/browserfs.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<!-- Matomo -->
<script type="text/javascript">
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://matomo.ethereum.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '27']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head> </head>
<body> <body>
<script> <script>
......
...@@ -6,6 +6,7 @@ const csjs = require('csjs-inject') ...@@ -6,6 +6,7 @@ const csjs = require('csjs-inject')
const EventEmitter = require('events') const EventEmitter = require('events')
const LocalPlugin = require('./local-plugin') const LocalPlugin = require('./local-plugin')
const addToolTip = require('../ui/tooltip') const addToolTip = require('../ui/tooltip')
const _paq = window._paq = window._paq || []
const css = csjs` const css = csjs`
.pluginSearch { .pluginSearch {
...@@ -101,6 +102,16 @@ class PluginManagerComponent extends ViewPlugin { ...@@ -101,6 +102,16 @@ class PluginManagerComponent extends ViewPlugin {
return this.appManager.actives.includes(name) return this.appManager.actives.includes(name)
} }
activateP (name) {
this.appManager.activatePlugin(name)
_paq.push(['trackEvent', 'manager', 'activate', name])
}
deactivateP (name) {
this.appManager.deactivatePlugin(name)
_paq.push(['trackEvent', 'manager', 'deactivate', name])
}
renderItem (profile) { renderItem (profile) {
const displayName = (profile.displayName) ? profile.displayName : profile.name const displayName = (profile.displayName) ? profile.displayName : profile.name
...@@ -118,7 +129,7 @@ class PluginManagerComponent extends ViewPlugin { ...@@ -118,7 +129,7 @@ class PluginManagerComponent extends ViewPlugin {
const activationButton = this.isActive(profile.name) const activationButton = this.isActive(profile.name)
? yo` ? yo`
<button <button
onclick="${_ => this.appManager.deactivatePlugin(profile.name)}" onclick="${() => this.deactivateP(profile.name)}"
class="btn btn-secondary btn-sm" data-id="pluginManagerComponentDeactivateButton${profile.name}" class="btn btn-secondary btn-sm" data-id="pluginManagerComponentDeactivateButton${profile.name}"
> >
Deactivate Deactivate
...@@ -126,7 +137,7 @@ class PluginManagerComponent extends ViewPlugin { ...@@ -126,7 +137,7 @@ class PluginManagerComponent extends ViewPlugin {
` `
: yo` : yo`
<button <button
onclick="${_ => this.appManager.activatePlugin(profile.name)}" onclick="${() => this.activateP(profile.name)}"
class="btn btn-success btn-sm" data-id="pluginManagerComponentActivateButton${profile.name}" class="btn btn-success btn-sm" data-id="pluginManagerComponentActivateButton${profile.name}"
> >
Activate Activate
......
import publishToStorage from '../../../publishToStorage' import publishToStorage from '../../../publishToStorage'
const yo = require('yo-yo') const yo = require('yo-yo')
const ethJSUtil = require('ethereumjs-util')
const css = require('../styles/run-tab-styles') const css = require('../styles/run-tab-styles')
const modalDialogCustom = require('../../ui/modal-dialog-custom') const modalDialogCustom = require('../../ui/modal-dialog-custom')
const remixLib = require('@remix-project/remix-lib') const remixLib = require('@remix-project/remix-lib')
...@@ -97,7 +97,8 @@ class ContractDropdownUI { ...@@ -97,7 +97,8 @@ class ContractDropdownUI {
enableAtAddress (enable) { enableAtAddress (enable) {
if (enable) { if (enable) {
if (this.atAddressButtonInput.value === '') return const address = this.atAddressButtonInput.value
if (!address || !ethJSUtil.isValidChecksumAddress(address)) return
this.atAddress.removeAttribute('disabled') this.atAddress.removeAttribute('disabled')
this.atAddress.setAttribute('title', 'Interact with the given contract.') this.atAddress.setAttribute('title', 'Interact with the given contract.')
} else { } else {
......
var ethJSUtil = require('ethereumjs-util')
var remixLib = require('@remix-project/remix-lib') var remixLib = require('@remix-project/remix-lib')
var txHelper = remixLib.execution.txHelper var txHelper = remixLib.execution.txHelper
var CompilerAbstract = require('../../../compiler/compiler-abstract') var CompilerAbstract = require('../../../compiler/compiler-abstract')
...@@ -43,12 +42,6 @@ class DropdownLogic { ...@@ -43,12 +42,6 @@ class DropdownLogic {
} }
loadContractFromAddress (address, confirmCb, cb) { loadContractFromAddress (address, confirmCb, cb) {
if (!ethJSUtil.isValidAddress(address)) {
return cb('Invalid address.')
}
if (/[a-f]/.test(address) && /[A-F]/.test(address) && !ethJSUtil.isValidChecksumAddress(address)) {
return cb('Invalid checksum address.')
}
if (/.(.abi)$/.exec(this.config.get('currentFile'))) { if (/.(.abi)$/.exec(this.config.get('currentFile'))) {
confirmCb(() => { confirmCb(() => {
var abi var abi
......
...@@ -37,6 +37,9 @@ module.exports = class SettingsTab extends ViewPlugin { ...@@ -37,6 +37,9 @@ module.exports = class SettingsTab extends ViewPlugin {
optionVMLabel: null, optionVMLabel: null,
personal: null, personal: null,
personalLabel: null, personalLabel: null,
useMatomoAnalytics: null,
useMatomoAnalyticsLabel: null,
useMatomoAnalyticsMode: null,
warnPersonalMode: null, warnPersonalMode: null,
generateContractMetadata: null, generateContractMetadata: null,
generateContractMetadataLabel: null, generateContractMetadataLabel: null,
...@@ -117,6 +120,17 @@ module.exports = class SettingsTab extends ViewPlugin { ...@@ -117,6 +120,17 @@ module.exports = class SettingsTab extends ViewPlugin {
if (this.config.get('settings/personal-mode')) this._view.personal.setAttribute('checked', '') if (this.config.get('settings/personal-mode')) this._view.personal.setAttribute('checked', '')
elementStateChanged(self._view.personalLabel, !this.config.get('settings/personal-mode')) elementStateChanged(self._view.personalLabel, !this.config.get('settings/personal-mode'))
this._view.useMatomoAnalytics = yo`<input onchange=${onchangeMatomoAnalytics} id="settingsMatomoAnalytics" type="checkbox" class="custom-control-input">`
this._view.useMatomoAnalyticsMode = yo`<i class="${css.icon} fas fa-exclamation-triangle text-warning" aria-hidden="true"></i>`
this._view.useMatomoAnalyticsLabel = yo`
<label class="form-check-label custom-control-label text-secondary align-middle" for="settingsMatomoAnalytics">
<span>${this._view.useMatomoAnalyticsMode} Enable Matomo Analytics. The statystics we are collecting is helping to improve plugins usage. We choose Matomo Analytics which is </span>
<a target="_blank" href="https://matomo.org/free-software">open source</a>
</label>
`
if (this.config.get('settings/matomo-analytics')) this._view.useMatomoAnalytics.setAttribute('checked', '')
elementStateChanged(self._view.personalLabel, !this.config.get('settings/matomo-analytics'))
this._view.generateContractMetadata = yo`<input onchange=${onchangeGenerateContractMetadata} id="generatecontractmetadata" data-id="settingsTabGenerateContractMetadata" type="checkbox" class="custom-control-input">` this._view.generateContractMetadata = yo`<input onchange=${onchangeGenerateContractMetadata} id="generatecontractmetadata" data-id="settingsTabGenerateContractMetadata" type="checkbox" class="custom-control-input">`
this._view.generateContractMetadataLabel = yo`<label class="form-check-label custom-control-label align-middle" data-id="settingsTabGenerateContractMetadataLabel" for="generatecontractmetadata">Generate contract metadata. Generate a JSON file in the contract folder. Allows to specify library addresses the contract depends on. If nothing is specified, Remix deploys libraries automatically.</label>` this._view.generateContractMetadataLabel = yo`<label class="form-check-label custom-control-label align-middle" data-id="settingsTabGenerateContractMetadataLabel" for="generatecontractmetadata">Generate contract metadata. Generate a JSON file in the contract folder. Allows to specify library addresses the contract depends on. If nothing is specified, Remix deploys libraries automatically.</label>`
if (this.config.get('settings/generate-contract-metadata') === undefined) this.config.set('settings/generate-contract-metadata', true) if (this.config.get('settings/generate-contract-metadata') === undefined) this.config.set('settings/generate-contract-metadata', true)
...@@ -145,9 +159,13 @@ module.exports = class SettingsTab extends ViewPlugin { ...@@ -145,9 +159,13 @@ module.exports = class SettingsTab extends ViewPlugin {
${this._view.textWrapLabel} ${this._view.textWrapLabel}
</div> </div>
<div class="custom-control custom-checkbox mb-1"> <div class="custom-control custom-checkbox mb-1">
${this._view.personal}> ${this._view.personal}
${this._view.personalLabel} ${this._view.personalLabel}
</div> </div>
<div class="custom-control custom-checkbox mb-1">
${this._view.useMatomoAnalytics}
${this._view.useMatomoAnalyticsLabel}
</div>
</div> </div>
</div> </div>
` `
...@@ -200,6 +218,16 @@ module.exports = class SettingsTab extends ViewPlugin { ...@@ -200,6 +218,16 @@ module.exports = class SettingsTab extends ViewPlugin {
self.config.set('settings/personal-mode', !isChecked) self.config.set('settings/personal-mode', !isChecked)
elementStateChanged(self._view.personalLabel, isChecked) elementStateChanged(self._view.personalLabel, isChecked)
} }
function onchangeMatomoAnalytics (event) {
elementStateChanged(self._view.useMatomoAnalyticsLabel, event.target.checked)
const _paq = window._paq = window._paq || []
if (this.checked) {
_paq.push(['forgetUserOptOut'])
} else {
_paq.push(['optUserOut'])
}
}
function elementStateChanged (el, isChanged) { function elementStateChanged (el, isChanged) {
if (isChanged) { if (isChanged) {
el.classList.remove('text-dark') el.classList.remove('text-dark')
......
...@@ -5,10 +5,11 @@ const yo = require('yo-yo') ...@@ -5,10 +5,11 @@ const yo = require('yo-yo')
const csjs = require('csjs-inject') const csjs = require('csjs-inject')
const globalRegistry = require('../../../global/registry') const globalRegistry = require('../../../global/registry')
const CompilerImport = require('../../compiler/compiler-imports') const CompilerImport = require('../../compiler/compiler-imports')
var modalDialogCustom = require('../modal-dialog-custom') const modalDialogCustom = require('../modal-dialog-custom')
var tooltip = require('../tooltip') const tooltip = require('../tooltip')
var GistHandler = require('../../../lib/gist-handler') const GistHandler = require('../../../lib/gist-handler')
var QueryParams = require('../../../lib/query-params.js') const QueryParams = require('../../../lib/query-params.js')
const _paq = window._paq = window._paq || []
const css = csjs` const css = csjs`
.text { .text {
...@@ -219,10 +220,12 @@ export class LandingPage extends ViewPlugin { ...@@ -219,10 +220,12 @@ export class LandingPage extends ViewPlugin {
this.mediumPanel.classList.remove('d-block') this.mediumPanel.classList.remove('d-block')
this.mediumPanel.classList.add('d-none') this.mediumPanel.classList.add('d-none')
this.twitterPanel.classList.toggle('d-block') this.twitterPanel.classList.toggle('d-block')
_paq.push(['trackEvent', 'pluginManager', 'media', 'twitter'])
} else { } else {
this.twitterPanel.classList.remove('d-block') this.twitterPanel.classList.remove('d-block')
this.twitterPanel.classList.add('d-none') this.twitterPanel.classList.add('d-none')
this.mediumPanel.classList.toggle('d-block') this.mediumPanel.classList.toggle('d-block')
_paq.push(['trackEvent', 'pluginManager', 'media', 'medium'])
} }
} }
...@@ -258,22 +261,27 @@ export class LandingPage extends ViewPlugin { ...@@ -258,22 +261,27 @@ export class LandingPage extends ViewPlugin {
const startSolidity = async () => { const startSolidity = async () => {
await this.appManager.activatePlugin(['solidity', 'udapp', 'solidityStaticAnalysis', 'solidityUnitTesting']) await this.appManager.activatePlugin(['solidity', 'udapp', 'solidityStaticAnalysis', 'solidityUnitTesting'])
this.verticalIcons.select('solidity') this.verticalIcons.select('solidity')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'solidity'])
} }
const startDebugger = async () => { const startDebugger = async () => {
await this.appManager.activatePlugin('debugger') await this.appManager.activatePlugin('debugger')
this.verticalIcons.select('debugger') this.verticalIcons.select('debugger')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'debugger'])
} }
const startSolhint = async () => { const startSolhint = async () => {
await this.appManager.activatePlugin(['solidity', 'solhint']) await this.appManager.activatePlugin(['solidity', 'solhint'])
this.verticalIcons.select('solhint') this.verticalIcons.select('solhint')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'solhint'])
} }
const startLearnEth = async () => { const startLearnEth = async () => {
await this.appManager.activatePlugin(['solidity', 'LearnEth', 'solidityUnitTesting']) await this.appManager.activatePlugin(['solidity', 'LearnEth', 'solidityUnitTesting'])
this.verticalIcons.select('LearnEth') this.verticalIcons.select('LearnEth')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'learnEth'])
} }
const startSourceVerify = async () => { const startSourceVerify = async () => {
await this.appManager.activatePlugin(['solidity', 'source-verification']) await this.appManager.activatePlugin(['solidity', 'source-verification'])
this.verticalIcons.select('source-verification') this.verticalIcons.select('source-verification')
_paq.push(['trackEvent', 'pluginManager', 'userActivate', 'source-verification'])
} }
const startPluginManager = async () => { const startPluginManager = async () => {
await this.appManager.activatePlugin('pluginManager') await this.appManager.activatePlugin('pluginManager')
......
...@@ -4,6 +4,7 @@ import { IframePlugin } from '@remixproject/engine-web' ...@@ -4,6 +4,7 @@ import { IframePlugin } from '@remixproject/engine-web'
import { EventEmitter } from 'events' import { EventEmitter } from 'events'
import QueryParams from './lib/query-params' import QueryParams from './lib/query-params'
import { PermissionHandler } from './app/ui/persmission-handler' import { PermissionHandler } from './app/ui/persmission-handler'
const _paq = window._paq = window._paq || []
const requiredModules = [ // services + layout views + system views const requiredModules = [ // services + layout views + system views
'manager', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme', 'manager', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme',
...@@ -65,6 +66,7 @@ export class RemixAppManager extends PluginManager { ...@@ -65,6 +66,7 @@ export class RemixAppManager extends PluginManager {
onPluginActivated (plugin) { onPluginActivated (plugin) {
this.pluginLoader.set(plugin, this.actives) this.pluginLoader.set(plugin, this.actives)
this.event.emit('activate', plugin) this.event.emit('activate', plugin)
_paq.push(['trackEvent', 'pluginManager', 'activate', plugin.name])
} }
getAll () { getAll () {
...@@ -80,6 +82,7 @@ export class RemixAppManager extends PluginManager { ...@@ -80,6 +82,7 @@ export class RemixAppManager extends PluginManager {
onPluginDeactivated (plugin) { onPluginDeactivated (plugin) {
this.pluginLoader.set(plugin, this.actives) this.pluginLoader.set(plugin, this.actives)
this.event.emit('deactivate', plugin) this.event.emit('deactivate', plugin)
_paq.push(['trackEvent', 'pluginManager', 'deactivate', plugin.name])
} }
isRequired (name) { isRequired (name) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment