From c6713e93adcaeeba1ec559d44135bb62c76d2538 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 17 Nov 2017 13:23:25 -0800 Subject: Fix bug where gas param was not a string Prevented sending transactions. Fixes #2598 --- ui/app/components/customize-gas-modal/index.js | 2 +- ui/app/components/send/send-constants.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'ui') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 485dacf90..6d27702e8 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -244,7 +244,7 @@ CustomizeGasModal.prototype.render = function () { min: 1, // max: 100000, step: 1, - onChange: value => this.convertAndSetGasLimit(value), + onChange: value => this.convertAndSetGasLimit(String(value)), title: 'Gas Limit', copy: 'We calculate the suggested gas limit based on network success rates.', }), diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js index a961ffcd8..9c240972f 100644 --- a/ui/app/components/send/send-constants.js +++ b/ui/app/components/send/send-constants.js @@ -3,8 +3,8 @@ const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') const MIN_GAS_PRICE_HEX = (100000000).toString(16) const MIN_GAS_PRICE_DEC = '100000000' -const MIN_GAS_LIMIT_HEX = (21000).toString(16) -const MIN_GAS_LIMIT_DEC = 21000 +const MIN_GAS_LIMIT_DEC = '21000' +const MIN_GAS_LIMIT_HEX = (parseInt(MIN_GAS_LIMIT_DEC)).toString(16) const MIN_GAS_PRICE_GWEI = ethUtil.addHexPrefix(conversionUtil(MIN_GAS_PRICE_HEX, { fromDenomination: 'WEI', -- cgit From 28409294c3cd70ddbc9a9f3467d402c89e110261 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 20 Nov 2017 10:54:05 -0800 Subject: Remove unneeded type casting --- ui/app/components/customize-gas-modal/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 6d27702e8..485dacf90 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -244,7 +244,7 @@ CustomizeGasModal.prototype.render = function () { min: 1, // max: 100000, step: 1, - onChange: value => this.convertAndSetGasLimit(String(value)), + onChange: value => this.convertAndSetGasLimit(value), title: 'Gas Limit', copy: 'We calculate the suggested gas limit based on network success rates.', }), -- cgit From 597af980dd68c0252625e7cc5b6a6a223406fbc2 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 20 Nov 2017 14:03:47 -0800 Subject: Prevent multiple submissions of first time form --- ui/app/first-time/init-menu.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/first-time/init-menu.js b/ui/app/first-time/init-menu.js index cc7c51bd3..b4587f1ee 100644 --- a/ui/app/first-time/init-menu.js +++ b/ui/app/first-time/init-menu.js @@ -8,6 +8,8 @@ const actions = require('../actions') const Tooltip = require('../components/tooltip') const getCaretCoordinates = require('textarea-caret') +let isSubmitting = false + module.exports = connect(mapStateToProps)(InitializeMenuScreen) inherits(InitializeMenuScreen, Component) @@ -164,7 +166,10 @@ InitializeMenuScreen.prototype.createNewVaultAndKeychain = function () { return } - this.props.dispatch(actions.createNewVaultAndKeychain(password)) + if (!isSubmitting) { + isSubmitting = true + this.props.dispatch(actions.createNewVaultAndKeychain(password)) + } } InitializeMenuScreen.prototype.inputChanged = function (event) { -- cgit From 90fc4812bc75857581e56eb6d63484dbc5c48cb1 Mon Sep 17 00:00:00 2001 From: "Clark, Jason (Contractor)" Date: Thu, 23 Nov 2017 18:33:44 -0700 Subject: incremental commit --- ui/app/actions.js | 9 +++++++++ ui/app/components/identicon.js | 3 ++- ui/app/reducers/metamask.js | 6 ++++++ ui/app/settings.js | 25 +++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 2ca62c41f..957e42223 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -234,6 +234,9 @@ var actions = { toggleAccountMenu, useEtherscanProvider, + + TOGGLE_USE_BLOCKIE: 'TOGGLE_USE_BLOCKIE', + toggleUseBlockie, } module.exports = actions @@ -1550,3 +1553,9 @@ function toggleAccountMenu () { type: actions.TOGGLE_ACCOUNT_MENU, } } + +function toggleUseBlockie () { + return { + type: actions.TOGGLE_USE_BLOCKIE, + } +} diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index d30b7cd56..63f3087a4 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const isNode = require('detect-node') const findDOMNode = require('react-dom').findDOMNode const jazzicon = require('jazzicon') +const blockies = require('blockies') const iconFactoryGen = require('../../lib/icon-factory') const iconFactory = iconFactoryGen(jazzicon) @@ -18,7 +19,7 @@ function IdenticonComponent () { IdenticonComponent.prototype.render = function () { var props = this.props - const { className = '', address } = props + const { className = '', address, useBlockie } = props var diameter = props.diameter || this.defaultDiameter return address diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 83161320e..ee496dc6f 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -36,6 +36,7 @@ function reduceMetamask (state, action) { editingTransactionId: null, }, coinOptions: {}, + useBlockie: false, }, state.metamask) switch (action.type) { @@ -314,6 +315,11 @@ function reduceMetamask (state, action) { coinOptions, }) + case actions.TOGGLE_USE_BLOCKIE: + return extend(metamaskState, { + useBlockie: !metamaskState.useBlockie, + }) + default: return metamaskState diff --git a/ui/app/settings.js b/ui/app/settings.js index 786a70e7e..793906bdb 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -8,6 +8,7 @@ const validUrl = require('valid-url') const { exportAsFile } = require('./util') const TabBar = require('./components/tab-bar') const SimpleDropdown = require('./components/dropdowns/simple-dropdown') +import Switch from 'react-toggle-switch' const getInfuraCurrencyOptions = () => { const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { @@ -51,6 +52,26 @@ class Settings extends Component { ]) } + renderBlockieOptIn () { + const { metamask: { useBlockie }, toggleUseBlockie } = this.props + + return h('div.settings__content-row', [ + h('div.settings__content-item', [ + h('span', 'Use Blockie Identicon'), + ]), + h('div.settings__content-item', [ + h('div.settings__content-item-col', [ + + h(Switch, { + on: useBlockie, + onClick: event => toggleUseBlockie(), + }), + + ]), + ]), + ]) + } + renderCurrentConversion () { const { metamask: { currentCurrency, conversionDate }, setCurrentCurrency } = this.props @@ -214,6 +235,7 @@ class Settings extends Component { return ( h('div.settings__content', [ warning && h('div.settings__error', warning), + this.renderBlockieOptIn(), this.renderCurrentConversion(), // this.renderCurrentProvider(), this.renderNewRpcUrl(), @@ -335,6 +357,7 @@ class Settings extends Component { Settings.propTypes = { tab: PropTypes.string, metamask: PropTypes.object, + useBlockie: PropTypes.bool, setCurrentCurrency: PropTypes.func, setRpcTarget: PropTypes.func, displayWarning: PropTypes.func, @@ -347,6 +370,7 @@ const mapStateToProps = state => { return { metamask: state.metamask, warning: state.appState.warning, + useBlockie: state.useBlockie, } } @@ -357,6 +381,7 @@ const mapDispatchToProps = dispatch => { setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)), displayWarning: warning => dispatch(actions.displayWarning(warning)), revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()), + toggleUseBlockie: () => dispatch(actions.toggleUseBlockie()), } } -- cgit From fc46a16a329df296cb565e3a0b04f268d2aeceb5 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Fri, 24 Nov 2017 10:35:17 -0700 Subject: toggle wired up to preferences property store --- ui/app/actions.js | 23 +++++++++++++++++------ ui/app/reducers/metamask.js | 8 ++++---- ui/app/settings.js | 19 +++++++++---------- 3 files changed, 30 insertions(+), 20 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 957e42223..2819742e5 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -235,8 +235,8 @@ var actions = { useEtherscanProvider, - TOGGLE_USE_BLOCKIE: 'TOGGLE_USE_BLOCKIE', - toggleUseBlockie, + SET_USE_BLOCKIE: 'SET_USE_BLOCKIE', + setUseBlockie, } module.exports = actions @@ -1554,8 +1554,19 @@ function toggleAccountMenu () { } } -function toggleUseBlockie () { - return { - type: actions.TOGGLE_USE_BLOCKIE, +function setUseBlockie (val) { + return (dispatch) => { + dispatch(actions.showLoadingIndication()) + log.debug(`background.setUseBlockie`) + background.setUseBlockie(val, (err) => { + dispatch(actions.hideLoadingIndication()) + if (err) { + return dispatch(actions.displayWarning(err.message)) + } + }) + dispatch({ + type: actions.SET_USE_BLOCKIE, + value: val + }) } -} +} \ No newline at end of file diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index ee496dc6f..1b747e188 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -315,10 +315,10 @@ function reduceMetamask (state, action) { coinOptions, }) - case actions.TOGGLE_USE_BLOCKIE: - return extend(metamaskState, { - useBlockie: !metamaskState.useBlockie, - }) + case actions.SET_USE_BLOCKIE: + return extend(metamaskState, { + useBlockie: action.value + }) default: return metamaskState diff --git a/ui/app/settings.js b/ui/app/settings.js index 793906bdb..949cbfb26 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -8,7 +8,7 @@ const validUrl = require('valid-url') const { exportAsFile } = require('./util') const TabBar = require('./components/tab-bar') const SimpleDropdown = require('./components/dropdowns/simple-dropdown') -import Switch from 'react-toggle-switch' +const ToggleButton = require('react-toggle-button') const getInfuraCurrencyOptions = () => { const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { @@ -53,7 +53,7 @@ class Settings extends Component { } renderBlockieOptIn () { - const { metamask: { useBlockie }, toggleUseBlockie } = this.props + const { metamask: { useBlockie }, setUseBlockie } = this.props return h('div.settings__content-row', [ h('div.settings__content-item', [ @@ -61,12 +61,12 @@ class Settings extends Component { ]), h('div.settings__content-item', [ h('div.settings__content-item-col', [ - - h(Switch, { - on: useBlockie, - onClick: event => toggleUseBlockie(), + h(ToggleButton, { + value: useBlockie, + onToggle: (value) => setUseBlockie(!value), + activeLabel: '', + inactiveLabel: '', }), - ]), ]), ]) @@ -357,7 +357,7 @@ class Settings extends Component { Settings.propTypes = { tab: PropTypes.string, metamask: PropTypes.object, - useBlockie: PropTypes.bool, + setUseBlockie: PropTypes.func, setCurrentCurrency: PropTypes.func, setRpcTarget: PropTypes.func, displayWarning: PropTypes.func, @@ -370,7 +370,6 @@ const mapStateToProps = state => { return { metamask: state.metamask, warning: state.appState.warning, - useBlockie: state.useBlockie, } } @@ -381,7 +380,7 @@ const mapDispatchToProps = dispatch => { setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)), displayWarning: warning => dispatch(actions.displayWarning(warning)), revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()), - toggleUseBlockie: () => dispatch(actions.toggleUseBlockie()), + setUseBlockie: value => dispatch(actions.setUseBlockie(value)), } } -- cgit From dc7bd3c62897edfb642f215a71fbf7dd93faa350 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Fri, 24 Nov 2017 13:48:56 -0700 Subject: incremental commit of working blockie component --- ui/app/components/blockies/blockies-component.js | 30 +++++++++++++++++ ui/app/components/identicon.js | 41 +++++++++++++++--------- 2 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 ui/app/components/blockies/blockies-component.js (limited to 'ui') diff --git a/ui/app/components/blockies/blockies-component.js b/ui/app/components/blockies/blockies-component.js new file mode 100644 index 000000000..d6defda16 --- /dev/null +++ b/ui/app/components/blockies/blockies-component.js @@ -0,0 +1,30 @@ +const Component = require('react').Component +const createElement = require('react').createElement +const blockies = require("ethereum-blockies"); + +class BlockiesIdenticon extends Component { + constructor(props) { + super(props); + } + getOpts () { + return { + seed: this.props.seed || "foo", + color: this.props.color || "#dfe", + bgcolor: this.props.bgcolor || "#a71", + size: this.props.size || 15, + scale: this.props.scale || 3, + spotcolor: this.props.spotcolor || "#000" + }; + } + componentDidMount() { + this.draw(); + } + draw() { + blockies.render(this.getOpts(), this.canvas); + } + render() { + return createElement("canvas", {ref: canvas => this.canvas = canvas}); + } +} + +module.exports = BlockiesIdenticon; diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 63f3087a4..9e9b82aae 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -1,14 +1,15 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const connect = require('react-redux').connect const isNode = require('detect-node') const findDOMNode = require('react-dom').findDOMNode const jazzicon = require('jazzicon') -const blockies = require('blockies') +const BlockiesIdenticon = require('./blockies/blockies-component') const iconFactoryGen = require('../../lib/icon-factory') const iconFactory = iconFactoryGen(jazzicon) -module.exports = IdenticonComponent +module.exports = connect(mapStateToProps)(IdenticonComponent) inherits(IdenticonComponent, Component) function IdenticonComponent () { @@ -17,6 +18,12 @@ function IdenticonComponent () { this.defaultDiameter = 46 } +function mapStateToProps (state) { + return { + useBlockie: state.metamask.useBlockie + } +} + IdenticonComponent.prototype.render = function () { var props = this.props const { className = '', address, useBlockie } = props @@ -24,19 +31,23 @@ IdenticonComponent.prototype.render = function () { return address ? ( - h('div', { - className: `${className} identicon`, - key: 'identicon-' + address, - style: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: diameter, - width: diameter, - borderRadius: diameter / 2, - overflow: 'hidden', - }, - }) + useBlockie + ? h(BlockiesIdenticon, { + seed: address, + }) + : h('div', { + className: `${className} identicon`, + key: 'identicon-' + address, + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: diameter, + width: diameter, + borderRadius: diameter / 2, + overflow: 'hidden', + }, + }) ) : ( h('img.balance-icon', { -- cgit From 41be4714c248870447c7593355f23023d63f24f6 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Fri, 24 Nov 2017 14:18:46 -0700 Subject: tweaking styling --- ui/app/components/blockies/blockies-component.js | 17 +++++++++++------ ui/app/components/identicon.js | 19 ++++++++++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'ui') diff --git a/ui/app/components/blockies/blockies-component.js b/ui/app/components/blockies/blockies-component.js index d6defda16..b3a97ced4 100644 --- a/ui/app/components/blockies/blockies-component.js +++ b/ui/app/components/blockies/blockies-component.js @@ -3,25 +3,30 @@ const createElement = require('react').createElement const blockies = require("ethereum-blockies"); class BlockiesIdenticon extends Component { + constructor(props) { super(props); } + getOpts () { return { - seed: this.props.seed || "foo", - color: this.props.color || "#dfe", - bgcolor: this.props.bgcolor || "#a71", - size: this.props.size || 15, - scale: this.props.scale || 3, - spotcolor: this.props.spotcolor || "#000" + seed: this.props.seed, + color: this.props.color, + bgcolor: this.props.bgcolor, + size: this.props.size, + scale: this.props.scale, + spotcolor: this.props.spotcolor, }; } + componentDidMount() { this.draw(); } + draw() { blockies.render(this.getOpts(), this.canvas); } + render() { return createElement("canvas", {ref: canvas => this.canvas = canvas}); } diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 9e9b82aae..c1dc0fb5c 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -32,9 +32,22 @@ IdenticonComponent.prototype.render = function () { return address ? ( useBlockie - ? h(BlockiesIdenticon, { - seed: address, - }) + ? h('div', { + className: `${className} identicon`, + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: diameter, + width: diameter, + borderRadius: diameter / 2, + overflow: 'hidden', + }, + }, [ + h(BlockiesIdenticon, { + seed: address + }) + ]) : h('div', { className: `${className} identicon`, key: 'identicon-' + address, -- cgit From 1b89ceb63aa7d96912eb32c8766ef566479dde41 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Sat, 25 Nov 2017 14:33:42 -0700 Subject: swapped out ethereum-blockies lib for MEW blockies library, tightened up identicon.js code --- ui/app/components/blockies/blockies-component.js | 35 --- ui/app/components/identicon.js | 99 +++--- ui/lib/blockies.js | 364 +++++++++++++++++++++++ 3 files changed, 413 insertions(+), 85 deletions(-) delete mode 100644 ui/app/components/blockies/blockies-component.js create mode 100644 ui/lib/blockies.js (limited to 'ui') diff --git a/ui/app/components/blockies/blockies-component.js b/ui/app/components/blockies/blockies-component.js deleted file mode 100644 index b3a97ced4..000000000 --- a/ui/app/components/blockies/blockies-component.js +++ /dev/null @@ -1,35 +0,0 @@ -const Component = require('react').Component -const createElement = require('react').createElement -const blockies = require("ethereum-blockies"); - -class BlockiesIdenticon extends Component { - - constructor(props) { - super(props); - } - - getOpts () { - return { - seed: this.props.seed, - color: this.props.color, - bgcolor: this.props.bgcolor, - size: this.props.size, - scale: this.props.scale, - spotcolor: this.props.spotcolor, - }; - } - - componentDidMount() { - this.draw(); - } - - draw() { - blockies.render(this.getOpts(), this.canvas); - } - - render() { - return createElement("canvas", {ref: canvas => this.canvas = canvas}); - } -} - -module.exports = BlockiesIdenticon; diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index c1dc0fb5c..3e2349dbe 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -5,9 +5,9 @@ const connect = require('react-redux').connect const isNode = require('detect-node') const findDOMNode = require('react-dom').findDOMNode const jazzicon = require('jazzicon') -const BlockiesIdenticon = require('./blockies/blockies-component') const iconFactoryGen = require('../../lib/icon-factory') const iconFactory = iconFactoryGen(jazzicon) +const { toDataUrl } = require('../../lib/blockies') module.exports = connect(mapStateToProps)(IdenticonComponent) @@ -31,36 +31,19 @@ IdenticonComponent.prototype.render = function () { return address ? ( - useBlockie - ? h('div', { - className: `${className} identicon`, - style: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: diameter, - width: diameter, - borderRadius: diameter / 2, - overflow: 'hidden', - }, - }, [ - h(BlockiesIdenticon, { - seed: address - }) - ]) - : h('div', { - className: `${className} identicon`, - key: 'identicon-' + address, - style: { - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - height: diameter, - width: diameter, - borderRadius: diameter / 2, - overflow: 'hidden', - }, - }) + h('div', { + className: `${className} identicon`, + key: useBlockie ? 'blockie' : 'identicon-' + address, + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: diameter, + width: diameter, + borderRadius: diameter / 2, + overflow: 'hidden', + }, + }) ) : ( h('img.balance-icon', { @@ -76,38 +59,54 @@ IdenticonComponent.prototype.render = function () { IdenticonComponent.prototype.componentDidMount = function () { var props = this.props - const { address } = props + const { address, useBlockie } = props if (!address) return - // eslint-disable-next-line react/no-find-dom-node - var container = findDOMNode(this) - - var diameter = props.diameter || this.defaultDiameter if (!isNode) { - var img = iconFactory.iconForAddress(address, diameter) - container.appendChild(img) + // eslint-disable-next-line react/no-find-dom-node + var container = findDOMNode(this) + + if (useBlockie) { + _generateBlockie(container, address) + } else { + const diameter = props.diameter || this.defaultDiameter + _generateJazzicon(container, address, diameter) + } } } IdenticonComponent.prototype.componentDidUpdate = function () { var props = this.props - const { address } = props + const { address, useBlockie } = props if (!address) return - // eslint-disable-next-line react/no-find-dom-node - var container = findDOMNode(this) - - var children = container.children - for (var i = 0; i < children.length; i++) { - container.removeChild(children[i]) - } - - var diameter = props.diameter || this.defaultDiameter if (!isNode) { - var img = iconFactory.iconForAddress(address, diameter) - container.appendChild(img) + // eslint-disable-next-line react/no-find-dom-node + var container = findDOMNode(this) + + var children = container.children + for (var i = 0; i < children.length; i++) { + container.removeChild(children[i]) + } + + if (useBlockie) { + _generateBlockie(container, address) + } else { + const diameter = props.diameter || this.defaultDiameter + _generateJazzicon(container, address, diameter) + } } } +function _generateBlockie(container, address) { + const img = new Image() + img.src = toDataUrl(address) + container.appendChild(img) +} + +function _generateJazzicon(container, address, diameter) { + const img = iconFactory.iconForAddress(address, diameter) + container.appendChild(img) +} diff --git a/ui/lib/blockies.js b/ui/lib/blockies.js new file mode 100644 index 000000000..ee5a2a5ca --- /dev/null +++ b/ui/lib/blockies.js @@ -0,0 +1,364 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.blockies = {}))); +}(this, (function (exports) { 'use strict'; + + /** + * A handy class to calculate color values. + * + * @version 1.0 + * @author Robert Eisele + * @copyright Copyright (c) 2010, Robert Eisele + * @link http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/ + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * + */ + + +// helper functions for that ctx + function write(buffer, offs) { + for (var i = 2; i < arguments.length; i++) { + for (var j = 0; j < arguments[i].length; j++) { + buffer[offs++] = arguments[i].charAt(j); + } + } + } + + function byte2(w) { + return String.fromCharCode((w >> 8) & 255, w & 255); + } + + function byte4(w) { + return String.fromCharCode((w >> 24) & 255, (w >> 16) & 255, (w >> 8) & 255, w & 255); + } + + function byte2lsb(w) { + return String.fromCharCode(w & 255, (w >> 8) & 255); + } + + var PNG = function(width,height,depth) { + + this.width = width; + this.height = height; + this.depth = depth; + + // pixel data and row filter identifier size + this.pix_size = height * (width + 1); + + // deflate header, pix_size, block headers, adler32 checksum + this.data_size = 2 + this.pix_size + 5 * Math.floor((0xfffe + this.pix_size) / 0xffff) + 4; + + // offsets and sizes of Png chunks + this.ihdr_offs = 0; // IHDR offset and size + this.ihdr_size = 4 + 4 + 13 + 4; + this.plte_offs = this.ihdr_offs + this.ihdr_size; // PLTE offset and size + this.plte_size = 4 + 4 + 3 * depth + 4; + this.trns_offs = this.plte_offs + this.plte_size; // tRNS offset and size + this.trns_size = 4 + 4 + depth + 4; + this.idat_offs = this.trns_offs + this.trns_size; // IDAT offset and size + this.idat_size = 4 + 4 + this.data_size + 4; + this.iend_offs = this.idat_offs + this.idat_size; // IEND offset and size + this.iend_size = 4 + 4 + 4; + this.buffer_size = this.iend_offs + this.iend_size; // total PNG size + + this.buffer = new Array(); + this.palette = new Object(); + this.pindex = 0; + + var _crc32 = new Array(); + + // initialize buffer with zero bytes + for (var i = 0; i < this.buffer_size; i++) { + this.buffer[i] = "\x00"; + } + + // initialize non-zero elements + write(this.buffer, this.ihdr_offs, byte4(this.ihdr_size - 12), 'IHDR', byte4(width), byte4(height), "\x08\x03"); + write(this.buffer, this.plte_offs, byte4(this.plte_size - 12), 'PLTE'); + write(this.buffer, this.trns_offs, byte4(this.trns_size - 12), 'tRNS'); + write(this.buffer, this.idat_offs, byte4(this.idat_size - 12), 'IDAT'); + write(this.buffer, this.iend_offs, byte4(this.iend_size - 12), 'IEND'); + + // initialize deflate header + var header = ((8 + (7 << 4)) << 8) | (3 << 6); + header+= 31 - (header % 31); + + write(this.buffer, this.idat_offs + 8, byte2(header)); + + // initialize deflate block headers + for (var i = 0; (i << 16) - 1 < this.pix_size; i++) { + var size, bits; + if (i + 0xffff < this.pix_size) { + size = 0xffff; + bits = "\x00"; + } else { + size = this.pix_size - (i << 16) - i; + bits = "\x01"; + } + write(this.buffer, this.idat_offs + 8 + 2 + (i << 16) + (i << 2), bits, byte2lsb(size), byte2lsb(~size)); + } + + /* Create crc32 lookup table */ + for (var i = 0; i < 256; i++) { + var c = i; + for (var j = 0; j < 8; j++) { + if (c & 1) { + c = -306674912 ^ ((c >> 1) & 0x7fffffff); + } else { + c = (c >> 1) & 0x7fffffff; + } + } + _crc32[i] = c; + } + + // compute the index into a png for a given pixel + this.index = function(x,y) { + var i = y * (this.width + 1) + x + 1; + var j = this.idat_offs + 8 + 2 + 5 * Math.floor((i / 0xffff) + 1) + i; + return j; + }; + + // convert a color and build up the palette + this.color = function(red, green, blue, alpha) { + + alpha = alpha >= 0 ? alpha : 255; + var color = (((((alpha << 8) | red) << 8) | green) << 8) | blue; + + if (typeof this.palette[color] == "undefined") { + if (this.pindex == this.depth) return "\x00"; + + var ndx = this.plte_offs + 8 + 3 * this.pindex; + + this.buffer[ndx + 0] = String.fromCharCode(red); + this.buffer[ndx + 1] = String.fromCharCode(green); + this.buffer[ndx + 2] = String.fromCharCode(blue); + this.buffer[this.trns_offs+8+this.pindex] = String.fromCharCode(alpha); + + this.palette[color] = String.fromCharCode(this.pindex++); + } + return this.palette[color]; + }; + + // output a PNG string, Base64 encoded + this.getBase64 = function() { + + var s = this.getDump(); + + var ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var c1, c2, c3, e1, e2, e3, e4; + var l = s.length; + var i = 0; + var r = ""; + + do { + c1 = s.charCodeAt(i); + e1 = c1 >> 2; + c2 = s.charCodeAt(i+1); + e2 = ((c1 & 3) << 4) | (c2 >> 4); + c3 = s.charCodeAt(i+2); + if (l < i+2) { e3 = 64; } else { e3 = ((c2 & 0xf) << 2) | (c3 >> 6); } + if (l < i+3) { e4 = 64; } else { e4 = c3 & 0x3f; } + r+= ch.charAt(e1) + ch.charAt(e2) + ch.charAt(e3) + ch.charAt(e4); + } while ((i+= 3) < l); + return r; + }; + + // output a PNG string + this.getDump = function() { + + // compute adler32 of output pixels + row filter bytes + var BASE = 65521; /* largest prime smaller than 65536 */ + var NMAX = 5552; /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + var s1 = 1; + var s2 = 0; + var n = NMAX; + + for (var y = 0; y < this.height; y++) { + for (var x = -1; x < this.width; x++) { + s1+= this.buffer[this.index(x, y)].charCodeAt(0); + s2+= s1; + if ((n-= 1) == 0) { + s1%= BASE; + s2%= BASE; + n = NMAX; + } + } + } + s1%= BASE; + s2%= BASE; + write(this.buffer, this.idat_offs + this.idat_size - 8, byte4((s2 << 16) | s1)); + + // compute crc32 of the PNG chunks + function crc32(png, offs, size) { + var crc = -1; + for (var i = 4; i < size-4; i += 1) { + crc = _crc32[(crc ^ png[offs+i].charCodeAt(0)) & 0xff] ^ ((crc >> 8) & 0x00ffffff); + } + write(png, offs+size-4, byte4(crc ^ -1)); + } + + crc32(this.buffer, this.ihdr_offs, this.ihdr_size); + crc32(this.buffer, this.plte_offs, this.plte_size); + crc32(this.buffer, this.trns_offs, this.trns_size); + crc32(this.buffer, this.idat_offs, this.idat_size); + crc32(this.buffer, this.iend_offs, this.iend_size); + + // convert PNG to string + return "\x89PNG\r\n\x1A\n"+this.buffer.join(''); + }; + + this.fillRect = function (x, y, w, h, color) { + for(var i = 0; i < w; i++) { + for (var j = 0; j < h; j++) { + this.buffer[this.index(x+i, y+j)] = color; + } + } + }; + }; + +// https://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion + /** + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 255]. + * + * @param {number} h The hue + * @param {number} s The saturation + * @param {number} l The lightness + * @return {Array} The RGB representation + */ + + function hue2rgb(p, q, t) { + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + function hsl2rgb(h, s, l){ + var r, g, b; + + if(s == 0){ + r = g = b = l; // achromatic + }else{ + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), 255]; + } + +// The random number is a js implementation of the Xorshift PRNG + var randseed = new Array(4); // Xorshift: [x, y, z, w] 32 bit values + + function seedrand(seed) { + for (var i = 0; i < randseed.length; i++) { + randseed[i] = 0; + } + for (var i = 0; i < seed.length; i++) { + randseed[i % 4] = (randseed[i % 4] << 5) - randseed[i % 4] + seed.charCodeAt(i); + } + } + + function rand() { + // based on Java's String.hashCode(), expanded to 4 32bit values + var t = randseed[0] ^ (randseed[0] << 11); + + randseed[0] = randseed[1]; + randseed[1] = randseed[2]; + randseed[2] = randseed[3]; + randseed[3] = randseed[3] ^ (randseed[3] >> 19) ^ t ^ (t >> 8); + + return (randseed[3] >>> 0) / (1 << 31 >>> 0); + } + + function createColor() { + //saturation is the whole color spectrum + var h = Math.floor(rand() * 360); + //saturation goes from 40 to 100, it avoids greyish colors + var s = rand() * 60 + 40; + //lightness can be anything from 0 to 100, but probabilities are a bell curve around 50% + var l = (rand() + rand() + rand() + rand()) * 25; + + return [h / 360,s / 100,l / 100]; + } + + function createImageData(size) { + var width = size; // Only support square icons for now + var height = size; + + var dataWidth = Math.ceil(width / 2); + var mirrorWidth = width - dataWidth; + + var data = []; + for (var y = 0; y < height; y++) { + var row = []; + for (var x = 0; x < dataWidth; x++) { + // this makes foreground and background color to have a 43% (1/2.3) probability + // spot color has 13% chance + row[x] = Math.floor(rand() * 2.3); + } + var r = row.slice(0, mirrorWidth); + r.reverse(); + row = row.concat(r); + + for (var i = 0; i < row.length; i++) { + data.push(row[i]); + } + } + + return data; + } + + function buildOpts(opts) { + if (!opts.seed) { + throw 'No seed provided' + } + + seedrand(opts.seed); + + return Object.assign({ + size: 8, + scale: 16, + color: createColor(), + bgcolor: createColor(), + spotcolor: createColor(), + }, opts) + } + + function toDataUrl(address) { + const opts = buildOpts({seed: address.toLowerCase()}); + + const imageData = createImageData(opts.size); + const width = Math.sqrt(imageData.length); + + const p = new PNG(opts.size*opts.scale, opts.size*opts.scale, 3); + const bgcolor = p.color(...hsl2rgb(...opts.bgcolor)); + const color = p.color(...hsl2rgb(...opts.color)); + const spotcolor = p.color(...hsl2rgb(...opts.spotcolor)); + + for (var i = 0; i < imageData.length; i++) { + var row = Math.floor(i / width); + var col = i % width; + // if data is 0, leave the background + if (imageData[i]) { + // if data is 2, choose spot color, if 1 choose foreground + const pngColor = imageData[i] == 1 ? color : spotcolor; + p.fillRect(col * opts.scale, row * opts.scale, opts.scale, opts.scale, pngColor); + } + } + return `data:image/png;base64,${p.getBase64()}`; + } + + exports.toDataUrl = toDataUrl; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); -- cgit From bd48d858f4226da889760e259377637164f3099c Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Sat, 25 Nov 2017 15:11:29 -0700 Subject: fixing blockies display issues --- ui/app/components/identicon.js | 12 ++++++++---- ui/app/settings.js | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'ui') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 3e2349dbe..7a3bd5394 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -67,10 +67,11 @@ IdenticonComponent.prototype.componentDidMount = function () { // eslint-disable-next-line react/no-find-dom-node var container = findDOMNode(this) + const diameter = props.diameter || this.defaultDiameter + if (useBlockie) { _generateBlockie(container, address) } else { - const diameter = props.diameter || this.defaultDiameter _generateJazzicon(container, address, diameter) } } @@ -91,18 +92,21 @@ IdenticonComponent.prototype.componentDidUpdate = function () { container.removeChild(children[i]) } + const diameter = props.diameter || this.defaultDiameter + if (useBlockie) { - _generateBlockie(container, address) + _generateBlockie(container, address, diameter) } else { - const diameter = props.diameter || this.defaultDiameter _generateJazzicon(container, address, diameter) } } } -function _generateBlockie(container, address) { +function _generateBlockie(container, address, diameter) { const img = new Image() img.src = toDataUrl(address) + const dia = !diameter || diameter < 50 ? 50 : diameter + img.height, img.width = dia * 1.25 container.appendChild(img) } diff --git a/ui/app/settings.js b/ui/app/settings.js index 949cbfb26..caa36d2b8 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -57,7 +57,7 @@ class Settings extends Component { return h('div.settings__content-row', [ h('div.settings__content-item', [ - h('span', 'Use Blockie Identicon'), + h('span', 'Use Blockies Identicon'), ]), h('div.settings__content-item', [ h('div.settings__content-item-col', [ -- cgit From 75ef848196646e060703764e97656ab3abd8c023 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Sat, 25 Nov 2017 15:47:34 -0700 Subject: making eslint happy --- ui/app/actions.js | 4 ++-- ui/app/components/identicon.js | 9 +++++---- ui/app/reducers/metamask.js | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 2819742e5..e79f4373e 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -1566,7 +1566,7 @@ function setUseBlockie (val) { }) dispatch({ type: actions.SET_USE_BLOCKIE, - value: val + value: val, }) } -} \ No newline at end of file +} diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 7a3bd5394..5b3786992 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -20,7 +20,7 @@ function IdenticonComponent () { function mapStateToProps (state) { return { - useBlockie: state.metamask.useBlockie + useBlockie: state.metamask.useBlockie, } } @@ -102,15 +102,16 @@ IdenticonComponent.prototype.componentDidUpdate = function () { } } -function _generateBlockie(container, address, diameter) { +function _generateBlockie (container, address, diameter) { const img = new Image() img.src = toDataUrl(address) const dia = !diameter || diameter < 50 ? 50 : diameter - img.height, img.width = dia * 1.25 + img.height = dia * 1.25 + img.width = dia * 1.25 container.appendChild(img) } -function _generateJazzicon(container, address, diameter) { +function _generateJazzicon (container, address, diameter) { const img = iconFactory.iconForAddress(address, diameter) container.appendChild(img) } diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 1b747e188..fb53bbaef 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -317,7 +317,7 @@ function reduceMetamask (state, action) { case actions.SET_USE_BLOCKIE: return extend(metamaskState, { - useBlockie: action.value + useBlockie: action.value, }) default: -- cgit From a34362b7765f48d24375c9953fa7c49cf3306491 Mon Sep 17 00:00:00 2001 From: Jason Clark Date: Mon, 27 Nov 2017 08:11:48 -0700 Subject: Fixes changes requested in pullrequestreview-79088534 --- ui/app/components/identicon.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 5b3786992..ddd7e65f3 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -33,7 +33,7 @@ IdenticonComponent.prototype.render = function () { ? ( h('div', { className: `${className} identicon`, - key: useBlockie ? 'blockie' : 'identicon-' + address, + key: 'identicon-' + address, style: { display: 'flex', alignItems: 'center', @@ -70,7 +70,7 @@ IdenticonComponent.prototype.componentDidMount = function () { const diameter = props.diameter || this.defaultDiameter if (useBlockie) { - _generateBlockie(container, address) + _generateBlockie(container, address, diameter) } else { _generateJazzicon(container, address, diameter) } -- cgit From f131468353aa518b8fc178cd591bfc7ab5bdc32c Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Tue, 28 Nov 2017 13:37:45 -0600 Subject: Remove useBlockie in props for render Removed unused useBlock for Lint validation. --- ui/app/components/identicon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index ddd7e65f3..b803b7ceb 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -26,7 +26,7 @@ function mapStateToProps (state) { IdenticonComponent.prototype.render = function () { var props = this.props - const { className = '', address, useBlockie } = props + const { className = '', address } = props var diameter = props.diameter || this.defaultDiameter return address -- cgit From 7dba114feb428f7f2f78fee5611377b04bff5be6 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 1 Dec 2017 14:19:53 -0800 Subject: Update font weights to 300, remove animation from network dropdown, fix network dropdown not closing from certain click-areas --- ui/app/components/dropdowns/network-dropdown.js | 27 +++++++++++++++---------- ui/app/components/network.js | 14 ++++++------- ui/app/css/itcss/components/account-menu.scss | 6 +++--- ui/app/css/itcss/components/menu.scss | 2 +- ui/app/css/itcss/components/newui-sections.scss | 2 +- 5 files changed, 28 insertions(+), 23 deletions(-) (limited to 'ui') diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 0908faf01..dfaa6b22c 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -6,6 +6,16 @@ const actions = require('../../actions') const Dropdown = require('./components/dropdown').Dropdown const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem const NetworkDropdownIcon = require('./components/network-dropdown-icon') +const R = require('ramda') + +// classes from nodes of the toggle element. +const notToggleElementClassnames = [ + 'menu-icon', + 'network-name', + 'network-indicator', + 'network-caret', + 'network-component', +] function mapStateToProps (state) { return { @@ -32,8 +42,8 @@ function mapDispatchToProps (dispatch) { showConfigPage: () => { dispatch(actions.showConfigPage()) }, - showNetworkDropdown: () => { dispatch(actions.showNetworkDropdown()) }, - hideNetworkDropdown: () => { dispatch(actions.hideNetworkDropdown()) }, + showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), + hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), } } @@ -59,18 +69,13 @@ NetworkDropdown.prototype.render = function () { } return h(Dropdown, { - useCssTransition: true, isOpen, onClickOutside: (event) => { const { classList } = event.target - const isNotToggleElement = [ - classList.contains('menu-icon'), - classList.contains('network-name'), - classList.contains('network-indicator'), - ].filter(bool => bool).length === 0 - // classes from three constituent nodes of the toggle element - - if (isNotToggleElement) { + const isInClassList = className => classList.contains(className) + const notToggleElementIndex = R.findIndex(isInClassList)(notToggleElementClassnames) + + if (notToggleElementIndex === -1) { this.props.hideNetworkDropdown() } }, diff --git a/ui/app/components/network.js b/ui/app/components/network.js index 915818009..5a8d0763d 100644 --- a/ui/app/components/network.js +++ b/ui/app/components/network.js @@ -39,7 +39,7 @@ Network.prototype.render = function () { }, src: 'images/loading.svg', }), - h('i.fa.fa-caret-down'), + h('i.fa.fa-caret-down.network-caret'), ]) } else if (providerName === 'mainnet') { hoverText = 'Main Ethereum Network' @@ -63,7 +63,7 @@ Network.prototype.render = function () { return ( h('div.network-component.pointer', { - className: classnames('network-component pointer', { + className: classnames({ 'network-component--disabled': this.props.disabled, 'ethereum-network': providerName === 'mainnet', 'ropsten-test-network': providerName === 'ropsten' || parseInt(networkNumber) === 3, @@ -90,7 +90,7 @@ Network.prototype.render = function () { color: '#039396', }}, 'Main Network'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) case 'ropsten-test-network': return h('.network-indicator', [ @@ -103,7 +103,7 @@ Network.prototype.render = function () { color: '#ff6666', }}, 'Ropsten Test Net'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) case 'kovan-test-network': return h('.network-indicator', [ @@ -116,7 +116,7 @@ Network.prototype.render = function () { color: '#690496', }}, 'Kovan Test Net'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) case 'rinkeby-test-network': return h('.network-indicator', [ @@ -129,7 +129,7 @@ Network.prototype.render = function () { color: '#e7a218', }}, 'Rinkeby Test Net'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) default: return h('.network-indicator', [ @@ -145,7 +145,7 @@ Network.prototype.render = function () { color: '#AEAEAE', }}, 'Private Network'), - h('i.fa.fa-caret-down.fa-lg'), + h('i.fa.fa-caret-down.fa-lg.network-caret'), ]) } })(), diff --git a/ui/app/css/itcss/components/account-menu.scss b/ui/app/css/itcss/components/account-menu.scss index e40e5a8c0..e16d2e024 100644 --- a/ui/app/css/itcss/components/account-menu.scss +++ b/ui/app/css/itcss/components/account-menu.scss @@ -40,7 +40,7 @@ font-size: 12px; line-height: 23px; padding: 0 24px; - font-weight: 200; + font-weight: 300; } img { @@ -113,7 +113,7 @@ &__name { color: $white; font-size: 18px; - font-weight: 200; + font-weight: 300; line-height: 16px; } @@ -126,7 +126,7 @@ &__action { font-size: 16px; line-height: 18px; - font-weight: 200; + font-weight: 300; cursor: pointer; } } diff --git a/ui/app/css/itcss/components/menu.scss b/ui/app/css/itcss/components/menu.scss index 17e24de98..7953834ee 100644 --- a/ui/app/css/itcss/components/menu.scss +++ b/ui/app/css/itcss/components/menu.scss @@ -12,7 +12,7 @@ align-items: center; position: relative; z-index: 200; - font-weight: 200; + font-weight: 300; @media screen and (max-width: 575px) { padding: 14px; diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index 244de2ba0..43a59c4da 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -248,7 +248,7 @@ $wallet-view-bg: $wild-sand; // wallet view .account-name { font-size: 24px; - font-weight: 200; + font-weight: 300; line-height: 20px; color: $scorpion; margin-top: 8px; -- cgit From a171b9b847bf0a889d1a29f51ddd475da8061874 Mon Sep 17 00:00:00 2001 From: Anatoli Babenia Date: Tue, 5 Dec 2017 00:46:19 +0300 Subject: Download State Logs with .json extension That doesn't fix #2095, but at least makes downloaded files syntax-highlighted when opened in editors --- ui/app/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/config.js b/ui/app/config.js index c14fa1d28..9cb2a0aad 100644 --- a/ui/app/config.js +++ b/ui/app/config.js @@ -117,7 +117,7 @@ ConfigScreen.prototype.render = function () { if (err) { state.dispatch(actions.displayWarning('Error in retrieving state logs.')) } else { - exportAsFile('MetaMask State Logs', result) + exportAsFile('MetaMask State Logs.json', result) } }) }, -- cgit From 7f795240706c013dc4a9ece0e9c9e33897c7fc71 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 14 Nov 2017 12:34:55 -0330 Subject: Add UI selection --- ui/app/actions.js | 29 +++++++++++++++++ ui/app/app.js | 60 ++++++++++++++++++++--------------- ui/app/css/index.scss | 1 + ui/app/css/itcss/components/menu.scss | 2 +- ui/app/reducers/metamask.js | 6 ++++ ui/app/root.js | 4 +-- ui/app/select-app.js | 21 ++++++++++++ 7 files changed, 94 insertions(+), 29 deletions(-) create mode 100644 ui/app/select-app.js (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index e79f4373e..745b8779e 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -237,6 +237,11 @@ var actions = { SET_USE_BLOCKIE: 'SET_USE_BLOCKIE', setUseBlockie, + + // Feature Flags + setFeatureFlag, + updateFeatureFlags, + UPDATE_FEATURE_FLAGS: 'UPDATE_FEATURE_FLAGS', } module.exports = actions @@ -1506,6 +1511,30 @@ function updateTokenExchangeRate (token = '') { } } +function setFeatureFlag (feature, activated) { + return (dispatch) => { + dispatch(actions.showLoadingIndication()) + return new Promise((resolve, reject) => { + background.setFeatureFlag(feature, activated, (err, updatedFeatureFlags) => { + dispatch(actions.hideLoadingIndication()) + if (err) { + dispatch(actions.displayWarning(err.message)) + reject(err) + } + dispatch(actions.updateFeatureFlags(updatedFeatureFlags)) + resolve(updatedFeatureFlags) + }) + }) + } +} + +function updateFeatureFlags (updatedFeatureFlags) { + return { + type: actions.UPDATE_FEATURE_FLAGS, + value: updatedFeatureFlags, + } +} + // Call Background Then Update // // A function generator for a common pattern wherein: diff --git a/ui/app/app.js b/ui/app/app.js index e90c3e98e..7e1eb200f 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -116,40 +116,41 @@ App.prototype.render = function () { log.debug('Main ui render function') return ( + h('.new-ui', [ + h('.flex-column.full-height', { + style: { + overflowX: 'hidden', + position: 'relative', + alignItems: 'center', + }, + }, [ - h('.flex-column.full-height', { - style: { - overflowX: 'hidden', - position: 'relative', - alignItems: 'center', - }, - }, [ - - // global modal - h(Modal, {}, []), + // global modal + h(Modal, {}, []), - // app bar - this.renderAppBar(), + // app bar + this.renderAppBar(), - // sidebar - this.renderSidebar(), + // sidebar + this.renderSidebar(), - // network dropdown - h(NetworkDropdown, { - provider: this.props.provider, - frequentRpcList: this.props.frequentRpcList, - }, []), + // network dropdown + h(NetworkDropdown, { + provider: this.props.provider, + frequentRpcList: this.props.frequentRpcList, + }, []), - h(AccountMenu), + h(AccountMenu), - (isLoading || isLoadingNetwork) && h(Loading, { - loadingMessage: loadMessage, - }), + (isLoading || isLoadingNetwork) && h(Loading, { + loadingMessage: loadMessage, + }), - // this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), + // this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), - // content - this.renderPrimary(), + // content + this.renderPrimary(), + ]) ]) ) } @@ -268,6 +269,13 @@ App.prototype.renderAppBar = function () { }, }, 'MetaMask'), + h('span', { + style: {}, + onClick: () => { + props.dispatch(actions.setFeatureFlag('betaUI', false)) + }, + }, 'Leave Beta') + ]), h('div.header__right-actions', [ diff --git a/ui/app/css/index.scss b/ui/app/css/index.scss index 01899ccad..445c819ff 100644 --- a/ui/app/css/index.scss +++ b/ui/app/css/index.scss @@ -4,6 +4,7 @@ http://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528 https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/ */ + @import './itcss/settings/index.scss'; @import './itcss/tools/index.scss'; @import './itcss/generic/index.scss'; diff --git a/ui/app/css/itcss/components/menu.scss b/ui/app/css/itcss/components/menu.scss index 17e24de98..77c49bbcf 100644 --- a/ui/app/css/itcss/components/menu.scss +++ b/ui/app/css/itcss/components/menu.scss @@ -11,7 +11,7 @@ flex-flow: row nowrap; align-items: center; position: relative; - z-index: 200; + z-index: 201; font-weight: 200; @media screen and (max-width: 575px) { diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index fb53bbaef..6d6068d05 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -37,6 +37,7 @@ function reduceMetamask (state, action) { }, coinOptions: {}, useBlockie: false, + featureFlags: {}, }, state.metamask) switch (action.type) { @@ -320,6 +321,11 @@ function reduceMetamask (state, action) { useBlockie: action.value, }) + case actions.UPDATE_FEATURE_FLAGS: + return extend(metamaskState, { + featureFlags: action.value, + }) + default: return metamaskState diff --git a/ui/app/root.js b/ui/app/root.js index 9e7314b20..21d6d1829 100644 --- a/ui/app/root.js +++ b/ui/app/root.js @@ -2,7 +2,7 @@ const inherits = require('util').inherits const Component = require('react').Component const Provider = require('react-redux').Provider const h = require('react-hyperscript') -const App = require('./app') +const SelectedApp = require('./select-app') module.exports = Root @@ -15,7 +15,7 @@ Root.prototype.render = function () { h(Provider, { store: this.props.store, }, [ - h(App), + h(SelectedApp), ]) ) diff --git a/ui/app/select-app.js b/ui/app/select-app.js new file mode 100644 index 000000000..3cba44052 --- /dev/null +++ b/ui/app/select-app.js @@ -0,0 +1,21 @@ +const inherits = require('util').inherits +const Component = require('react').Component +const connect = require('react-redux').connect +const h = require('react-hyperscript') +const App = require('./app') +const OldApp = require('../../old-ui/app/app') + +function mapStateToProps (state) { + return { betaUI: state.metamask.featureFlags.betaUI } +} + +module.exports = connect(mapStateToProps)(SelectedApp) + +inherits(SelectedApp, Component) +function SelectedApp () { Component.call(this) } + +SelectedApp.prototype.render = function () { + const { betaUI } = this.props + const Selected = betaUI ? App : OldApp + return h(Selected) +} -- cgit From ce14ee2ffcc784849ab42797d5c999b76ed57a78 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 15 Nov 2017 14:09:03 -0330 Subject: New-ui actions accomodates old-ui. --- ui/app/actions.js | 17 ++++++++++------- ui/app/reducers/metamask.js | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 745b8779e..bdacf3092 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -993,9 +993,10 @@ function showConfigPage (transitionForward = true) { } } -function showAddTokenPage () { +function showAddTokenPage (transitionForward = true) { return { type: actions.SHOW_ADD_TOKEN_PAGE, + value: transitionForward, } } @@ -1277,7 +1278,8 @@ function exportAccount (password, address) { return reject(err) } - dispatch(self.exportAccountComplete()) + // dispatch(self.exportAccountComplete()) + dispatch(self.showPrivateKey(result)) return resolve(result) }) @@ -1444,7 +1446,7 @@ function reshowQrCode (data, coin) { dispatch(actions.showLoadingIndication()) shapeShiftRequest('marketinfo', {pair: `${coin.toLowerCase()}_eth`}, (mktResponse) => { if (mktResponse.error) return dispatch(actions.displayWarning(mktResponse.error)) - + var message = [ `Deposit your ${coin} to the address bellow:`, `Deposit Limit: ${mktResponse.limit}`, @@ -1452,10 +1454,11 @@ function reshowQrCode (data, coin) { ] dispatch(actions.hideLoadingIndication()) - return dispatch(actions.showModal({ - name: 'SHAPESHIFT_DEPOSIT_TX', - Qr: { data, message }, - })) + return dispatch(actions.showQrView(data, message)) + // return dispatch(actions.showModal({ + // name: 'SHAPESHIFT_DEPOSIT_TX', + // Qr: { data, message }, + // })) }) } } diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 6d6068d05..c496625c7 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -311,7 +311,7 @@ function reduceMetamask (state, action) { return extend(metamaskState, { tokenExchangeRates: { ...metamaskState.tokenExchangeRates, - [marketinfo.pair]: ssMarketInfo, + [ssMarketInfo.pair]: ssMarketInfo, }, coinOptions, }) -- cgit From 84321b2d9b08a2b0f3e773cfb6f6d11dff9f7d4c Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 16 Nov 2017 15:58:59 -0330 Subject: Lint fix --- ui/app/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/app.js b/ui/app/app.js index 7e1eb200f..7cee07ea5 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -150,7 +150,7 @@ App.prototype.render = function () { // content this.renderPrimary(), - ]) + ]), ]) ) } @@ -274,7 +274,7 @@ App.prototype.renderAppBar = function () { onClick: () => { props.dispatch(actions.setFeatureFlag('betaUI', false)) }, - }, 'Leave Beta') + }, 'Leave Beta'), ]), -- cgit From 730d7f84ca8c202674677a6a6a94290e57ad9e3a Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 4 Dec 2017 15:30:45 -0330 Subject: Update newUI UI for switching back to old UI. --- ui/app/app.js | 7 ------- ui/app/settings.js | 25 ++++++++++++++++++++++++- 2 files changed, 24 insertions(+), 8 deletions(-) (limited to 'ui') diff --git a/ui/app/app.js b/ui/app/app.js index 7cee07ea5..88a5c8458 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -269,13 +269,6 @@ App.prototype.renderAppBar = function () { }, }, 'MetaMask'), - h('span', { - style: {}, - onClick: () => { - props.dispatch(actions.setFeatureFlag('betaUI', false)) - }, - }, 'Leave Beta'), - ]), h('div.header__right-actions', [ diff --git a/ui/app/settings.js b/ui/app/settings.js index caa36d2b8..ba59f1c76 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -229,6 +229,26 @@ class Settings extends Component { ) } + renderOldUI () { + const { setFeatureFlagToBeta } = this.props + + return ( + h('div.settings__content-row', [ + h('div.settings__content-item', 'Use old UI'), + h('div.settings__content-item', [ + h('div.settings__content-item-col', [ + h('button.settings__clear-button.settings__clear-button--red', { + onClick (event) { + event.preventDefault() + setFeatureFlagToBeta() + }, + }, 'Use old UI'), + ]), + ]), + ]) + ) + } + renderSettingsContent () { const { warning } = this.props @@ -241,10 +261,11 @@ class Settings extends Component { this.renderNewRpcUrl(), this.renderStateLogs(), this.renderSeedWords(), + this.renderOldUI(), ]) ) } - + renderLogo () { return ( h('div.settings__info-logo-wrapper', [ @@ -362,6 +383,7 @@ Settings.propTypes = { setRpcTarget: PropTypes.func, displayWarning: PropTypes.func, revealSeedConfirmation: PropTypes.func, + setFeatureFlagToBeta: PropTypes.func, warning: PropTypes.string, goHome: PropTypes.func, } @@ -381,6 +403,7 @@ const mapDispatchToProps = dispatch => { displayWarning: warning => dispatch(actions.displayWarning(warning)), revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()), setUseBlockie: value => dispatch(actions.setUseBlockie(value)), + setFeatureFlagToBeta: () => dispatch(actions.setFeatureFlag('betaUI', false)), } } -- cgit From 9db00fa507c04180f6425cc3b1e3187afa193ab8 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 4 Dec 2017 22:30:11 -0330 Subject: Show user notifications after switch between UIs --- ui/app/actions.js | 4 ++ ui/app/components/modals/modal.js | 37 +++++++++++++++++++ ui/app/components/modals/notification-modal.js | 51 ++++++++++++++++++++++++++ ui/app/css/itcss/components/modal.scss | 36 ++++++++++++++++++ ui/app/css/itcss/components/settings.scss | 5 +++ ui/app/settings.js | 4 +- 6 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 ui/app/components/modals/notification-modal.js (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index bdacf3092..bba2a014f 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -1515,6 +1515,9 @@ function updateTokenExchangeRate (token = '') { } function setFeatureFlag (feature, activated) { + const notificationType = activated + ? 'BETA_UI_NOTIFICATION_MODAL' + : 'OLD_UI_NOTIFICATION_MODAL' return (dispatch) => { dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { @@ -1525,6 +1528,7 @@ function setFeatureFlag (feature, activated) { reject(err) } dispatch(actions.updateFeatureFlags(updatedFeatureFlags)) + dispatch(actions.showModal({ name: notificationType })) resolve(updatedFeatureFlags) }) }) diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index f2909f3c3..2ff6accaa 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -16,6 +16,7 @@ const NewAccountModal = require('./new-account-modal') const ShapeshiftDepositTxModal = require('./shapeshift-deposit-tx-modal.js') const HideTokenConfirmationModal = require('./hide-token-confirmation-modal') const CustomizeGasModal = require('../customize-gas-modal') +const NotifcationModal = require('./notification-modal') const accountModalStyle = { mobileModalStyle: { @@ -133,6 +134,42 @@ const MODALS = { }, }, + BETA_UI_NOTIFICATION_MODAL: { + contents: [ + h(NotifcationModal, { + header: 'Welcome to the New UI (Beta)', + message: `You are now using the new Metamask UI. Take a look around, try out new features like sending tokens, + and let us know if you have any issues.`, + }), + ], + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + }, + laptopModalStyle: { + width: '449px', + top: 'calc(33% + 45px)', + }, + }, + + OLD_UI_NOTIFICATION_MODAL: { + contents: [ + h(NotifcationModal, { + header: 'Old UI', + message: `You have returned to the old UI. You can switch back to the New UI through the option in the top + right dropdown menu.`, + }), + ], + mobileModalStyle: { + width: '95%', + top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + }, + laptopModalStyle: { + width: '449px', + top: 'calc(33% + 45px)', + }, + }, + NEW_ACCOUNT: { contents: [ h(NewAccountModal, {}, []), diff --git a/ui/app/components/modals/notification-modal.js b/ui/app/components/modals/notification-modal.js new file mode 100644 index 000000000..239144b0c --- /dev/null +++ b/ui/app/components/modals/notification-modal.js @@ -0,0 +1,51 @@ +const { Component } = require('react') +const PropTypes = require('prop-types') +const h = require('react-hyperscript') +const { connect } = require('react-redux') +const actions = require('../../actions') + +class NotificationModal extends Component { + render () { + const { + header, + message, + } = this.props + + return h('div', [ + h('div.notification-modal-wrapper', { + }, [ + + h('div.notification-modal-header', {}, [ + header, + ]), + + h('div.notification-modal-message-wrapper', {}, [ + h('div.notification-modal-message', {}, [ + message, + ]), + ]), + + h('div.modal-close-x', { + onClick: this.props.hideModal, + }), + + ]), + ]) + } +} + +NotificationModal.propTypes = { + hideModal: PropTypes.func, + header: PropTypes.string, + message: PropTypes.string, +} + +const mapDispatchToProps = dispatch => { + return { + hideModal: () => { + dispatch(actions.hideModal()) + }, + } +} + +module.exports = connect(null, mapDispatchToProps)(NotificationModal) diff --git a/ui/app/css/itcss/components/modal.scss b/ui/app/css/itcss/components/modal.scss index b69bd5c7e..9b64564d6 100644 --- a/ui/app/css/itcss/components/modal.scss +++ b/ui/app/css/itcss/components/modal.scss @@ -563,3 +563,39 @@ } } } + +//Notification Modal + +.notification-modal-wrapper { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + position: relative; + border: 1px solid $alto; + box-shadow: 0 0 2px 2px $alto; + font-family: Roboto; +} + +.notification-modal-header { + background: $wild-sand; + width: 100%; + display: flex; + justify-content: center; + padding: 30px; + font-size: 22px; + color: $nile-blue; + height: 79px; +} + +.notification-modal-message { + padding: 20px; +} + +.notification-modal-message { + width: 100%; + display: flex; + justify-content: center; + font-size: 17px; + color: $nile-blue; +} \ No newline at end of file diff --git a/ui/app/css/itcss/components/settings.scss b/ui/app/css/itcss/components/settings.scss index 2f29d8017..d60ebd934 100644 --- a/ui/app/css/itcss/components/settings.scss +++ b/ui/app/css/itcss/components/settings.scss @@ -145,6 +145,11 @@ color: $monzo; } +.settings__clear-button--orange { + border: 1px solid rgba(247, 134, 28, 1); + color: rgba(247, 134, 28, 1); +} + .settings__info-logo-wrapper { height: 80px; margin-bottom: 20px; diff --git a/ui/app/settings.js b/ui/app/settings.js index ba59f1c76..ca7535d26 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -228,7 +228,7 @@ class Settings extends Component { ]) ) } - + renderOldUI () { const { setFeatureFlagToBeta } = this.props @@ -237,7 +237,7 @@ class Settings extends Component { h('div.settings__content-item', 'Use old UI'), h('div.settings__content-item', [ h('div.settings__content-item-col', [ - h('button.settings__clear-button.settings__clear-button--red', { + h('button.settings__clear-button.settings__clear-button--orange', { onClick (event) { event.preventDefault() setFeatureFlagToBeta() -- cgit From bd5ce9461e5119c13ab8be29db5cdfc57228bac8 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 6 Dec 2017 20:49:45 -0330 Subject: User is automatically added to new UI if they meet conditions at time of login. --- ui/app/select-app.js | 32 +++++++++++++++++++++++++++++--- ui/app/selectors.js | 18 ++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) (limited to 'ui') diff --git a/ui/app/select-app.js b/ui/app/select-app.js index 3cba44052..ffa31b767 100644 --- a/ui/app/select-app.js +++ b/ui/app/select-app.js @@ -4,18 +4,44 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const App = require('./app') const OldApp = require('../../old-ui/app/app') +const { autoAddToBetaUI } = require('./selectors') +const { setFeatureFlag } = require('./actions') function mapStateToProps (state) { - return { betaUI: state.metamask.featureFlags.betaUI } + return { + betaUI: state.metamask.featureFlags.betaUI, + autoAdd: autoAddToBetaUI(state), + isUnlocked: state.metamask.isUnlocked, + } } -module.exports = connect(mapStateToProps)(SelectedApp) +function mapDispatchToProps (dispatch) { + return { + setFeatureFlagToBeta: () => dispatch(setFeatureFlag('betaUI', true)), + } +} +module.exports = connect(mapStateToProps, mapDispatchToProps)(SelectedApp) inherits(SelectedApp, Component) -function SelectedApp () { Component.call(this) } +function SelectedApp () { + this.state = { + autoAdd: false, + } + Component.call(this) +} + +SelectedApp.prototype.componentWillReceiveProps = function (nextProps) { + const { isUnlocked, setFeatureFlagToBeta } = this.props + + if (!isUnlocked && nextProps.isUnlocked && nextProps.autoAdd) { + this.setState({ autoAdd: nextProps.autoAdd }) + setFeatureFlagToBeta() + } +} SelectedApp.prototype.render = function () { const { betaUI } = this.props + const { autoAdd } = this.state const Selected = betaUI ? App : OldApp return h(Selected) } diff --git a/ui/app/selectors.js b/ui/app/selectors.js index a5f9a75d8..8aea7864a 100644 --- a/ui/app/selectors.js +++ b/ui/app/selectors.js @@ -24,6 +24,7 @@ const selectors = { getSendAmount, getSelectedTokenToFiatRate, getSelectedTokenContract, + autoAddToBetaUI, } module.exports = selectors @@ -158,3 +159,20 @@ function getSelectedTokenContract (state) { ? global.eth.contract(abi).at(selectedToken.address) : null } + +function autoAddToBetaUI (state) { + const autoAddTransactionThreshold = 12 + const autoAddAccountsThreshold = 2 + const autoAddTokensThreshold = 1 + + const numberOfTransactions = state.metamask.selectedAddressTxList.length + const numberOfAccounts = Object.keys(state.metamask.accounts).length + const numberOfTokensAdded = state.metamask.tokens.length + + const userPassesThreshold = (numberOfTransactions > autoAddTransactionThreshold) && + (numberOfAccounts > autoAddAccountsThreshold) && + (numberOfTokensAdded > autoAddTokensThreshold) + const userIsNotInBeta = !state.metamask.featureFlags.betaUI + + return userIsNotInBeta && userPassesThreshold +} \ No newline at end of file -- cgit From 6ff580584a74c6d85f54ce7cfc500db822904957 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 22:20:11 -0500 Subject: Add retry background method and action --- ui/app/actions.js | 6 ++++++ ui/app/components/transaction-list-item.js | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 04fd35b20..2ab68b62d 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -168,6 +168,7 @@ var actions = { callBackgroundThenUpdate, forceUpdateMetamaskState, + retryTransaction, } module.exports = actions @@ -759,6 +760,11 @@ function markAccountsFound () { return callBackgroundThenUpdate(background.markAccountsFound) } +function retryTransaction () { + log.debug(`background.retryTransaction`) + return callBackgroundThenUpdate(background.retryTransaction) +} + // // config // diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 891d5e227..ddef4a4ae 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -9,6 +9,7 @@ const CopyButton = require('./copyButton') const vreme = new (require('vreme'))() const Tooltip = require('./tooltip') const numberToBN = require('number-to-bn') +const actions = require('../actions') const TransactionIcon = require('./transaction-list-item-icon') const ShiftListItem = require('./shift-list-item') @@ -21,6 +22,7 @@ function TransactionListItem () { TransactionListItem.prototype.render = function () { const { transaction, network, conversionRate, currentCurrency } = this.props + const { status } = transaction if (transaction.key === 'shapeshift') { if (network === '1') return h(ShiftListItem, transaction) } @@ -32,7 +34,7 @@ TransactionListItem.prototype.render = function () { var isMsg = ('msgParams' in transaction) var isTx = ('txParams' in transaction) - var isPending = transaction.status === 'unapproved' + var isPending = status === 'unapproved' let txParams if (isTx) { txParams = transaction.txParams @@ -97,10 +99,16 @@ TransactionListItem.prototype.render = function () { showFiat: false, style: {fontSize: '15px'}, }) : h('.flex-column'), + ]) ) } +TransactionListItem.prototype.resubmit = function () { + const { transaction } = this.props + this.props.dispatch(actions.resubmitTx(transaction.id)) +} + function domainField (txParams) { return h('div', { style: { -- cgit From 500fbe450a10e1a3c756707e44225b196601372e Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 6 Dec 2017 22:22:40 -0500 Subject: Add button to retry transaction --- ui/app/components/transaction-list-item.js | 103 +++++++++++++++++++---------- 1 file changed, 69 insertions(+), 34 deletions(-) (limited to 'ui') diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index ddef4a4ae..9c512a89d 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -46,7 +46,7 @@ TransactionListItem.prototype.render = function () { const isClickable = ('hash' in transaction && isLinkable) || isPending return ( - h(`.transaction-list-item.flex-row.flex-space-between${isClickable ? '.pointer' : ''}`, { + h('.transaction-list-item.flex-column', { onClick: (event) => { if (isPending) { this.props.showTx(transaction.id) @@ -58,48 +58,83 @@ TransactionListItem.prototype.render = function () { }, style: { padding: '20px 0', + alignItems: 'center', }, }, [ + h(`.flex-row.flex-space-between${isClickable ? '.pointer' : ''}`, { + style: { + width: '100%', + }, + }, [ + h('.identicon-wrapper.flex-column.flex-center.select-none', [ + h(TransactionIcon, { txParams, transaction, isTx, isMsg }), + ]), - h('.identicon-wrapper.flex-column.flex-center.select-none', [ - h(TransactionIcon, { txParams, transaction, isTx, isMsg }), + h(Tooltip, { + title: 'Transaction Number', + position: 'right', + }, [ + h('span', { + style: { + display: 'flex', + cursor: 'normal', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + padding: '10px', + }, + }, nonce), + ]), + + h('.flex-column', {style: {width: '200px', overflow: 'hidden'}}, [ + domainField(txParams), + h('div', date), + recipientField(txParams, transaction, isTx, isMsg), + ]), + + // Places a copy button if tx is successful, else places a placeholder empty div. + transaction.hash ? h(CopyButton, { value: transaction.hash }) : h('div', {style: { display: 'flex', alignItems: 'center', width: '26px' }}), + + isTx ? h(EthBalance, { + value: txParams.value, + conversionRate, + currentCurrency, + width: '55px', + shorten: true, + showFiat: false, + style: {fontSize: '15px'}, + }) : h('.flex-column'), ]), - h(Tooltip, { - title: 'Transaction Number', - position: 'right', + transaction.status === 'submitted' && h('.transition-list-item__retry', { + onClick: event => { + event.stopPropagation() + this.resubmit() + }, + style: { + height: '30px', + borderRadius: '30px', + color: '#F9881B', + padding: '0 25px', + backgroundColor: '#FFE3C9', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + fontSize: '9px', + cursor: 'pointer', + }, }, [ - h('span', { + h('div', { style: { - display: 'flex', - cursor: 'normal', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - padding: '10px', + paddingRight: '2px', }, - }, nonce), - ]), - - h('.flex-column', {style: {width: '200px', overflow: 'hidden'}}, [ - domainField(txParams), - h('div', date), - recipientField(txParams, transaction, isTx, isMsg), + }, 'Taking too long?'), + h('div', { + style: { + textDecoration: 'underline', + }, + }, 'Retry with a higher gas price here'), ]), - - // Places a copy button if tx is successful, else places a placeholder empty div. - transaction.hash ? h(CopyButton, { value: transaction.hash }) : h('div', {style: { display: 'flex', alignItems: 'center', width: '26px' }}), - - isTx ? h(EthBalance, { - value: txParams.value, - conversionRate, - currentCurrency, - width: '55px', - shorten: true, - showFiat: false, - style: {fontSize: '15px'}, - }) : h('.flex-column'), - ]) ) } -- cgit From 02736d2d361a415f145404a96f553c73e3707eb5 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 6 Dec 2017 22:48:26 -0500 Subject: Connect to redux for retryTransaction --- ui/app/components/transaction-list-item.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 9c512a89d..56e90e26c 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -1,6 +1,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits +const connect = require('react-redux').connect const EthBalance = require('./eth-balance') const addressSummary = require('../util').addressSummary @@ -13,7 +14,14 @@ const actions = require('../actions') const TransactionIcon = require('./transaction-list-item-icon') const ShiftListItem = require('./shift-list-item') -module.exports = TransactionListItem + +const mapDispatchToProps = dispatch => { + return { + retryTransaction: transactionId => dispatch(actions.retryTransaction(transactionId)), + } +} + +module.exports = connect(null, mapDispatchToProps)(TransactionListItem) inherits(TransactionListItem, Component) function TransactionListItem () { @@ -141,7 +149,7 @@ TransactionListItem.prototype.render = function () { TransactionListItem.prototype.resubmit = function () { const { transaction } = this.props - this.props.dispatch(actions.resubmitTx(transaction.id)) + this.props.retryTransaction(transaction.id) } function domainField (txParams) { -- cgit From 97abbc5cbe97157304f27f0f20336b543de62428 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 22:55:47 -0500 Subject: Fix action --- ui/app/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 2ab68b62d..35eb4b0c8 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -760,9 +760,9 @@ function markAccountsFound () { return callBackgroundThenUpdate(background.markAccountsFound) } -function retryTransaction () { +function retryTransaction (txId) { log.debug(`background.retryTransaction`) - return callBackgroundThenUpdate(background.retryTransaction) + return callBackgroundThenUpdate(background.retryTransaction, txId) } // -- cgit From 81fb9db1bcd08fb4e92d87d0c0905cb02dac63c2 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 23:09:32 -0500 Subject: View tx after editing state to unconfirmed --- ui/app/actions.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 35eb4b0c8..0dc4f3832 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -762,7 +762,15 @@ function markAccountsFound () { function retryTransaction (txId) { log.debug(`background.retryTransaction`) - return callBackgroundThenUpdate(background.retryTransaction, txId) + return (dispatch) => { + background.retryTransaction(txId, (err) => { + if (err) { + return dispatch(actions.displayWarning(err.message)) + } + forceUpdateMetamaskState(dispatch) + dispatch(actions.viewPendingTx(txId)) + }) + } } // -- cgit From 31564e0a86072ae2b49923dcf28983075308c432 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 23:20:15 -0500 Subject: Fix retry action --- ui/app/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 0dc4f3832..52ea899aa 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -763,11 +763,11 @@ function markAccountsFound () { function retryTransaction (txId) { log.debug(`background.retryTransaction`) return (dispatch) => { - background.retryTransaction(txId, (err) => { + background.retryTransaction(txId, (err, newState) => { if (err) { return dispatch(actions.displayWarning(err.message)) } - forceUpdateMetamaskState(dispatch) + dispatch(actions.updateMetamaskState(newState)) dispatch(actions.viewPendingTx(txId)) }) } -- cgit From 6b3909547f14533cfe09e3d12ac61f0cf57eedd4 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Wed, 6 Dec 2017 23:27:43 -0500 Subject: Fix styling of Retry buton --- ui/app/components/transaction-list-item.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ui') diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index 56e90e26c..fa6c5915d 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -120,15 +120,15 @@ TransactionListItem.prototype.render = function () { this.resubmit() }, style: { - height: '30px', - borderRadius: '30px', + height: '22px', + borderRadius: '22px', color: '#F9881B', - padding: '0 25px', + padding: '0 20px', backgroundColor: '#FFE3C9', display: 'flex', justifyContent: 'center', alignItems: 'center', - fontSize: '9px', + fontSize: '8px', cursor: 'pointer', }, }, [ -- cgit From 0e25129028dd45d717d27dfe0c06db8a4052bd4e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 6 Dec 2017 23:42:47 -0500 Subject: Enforce retry tx at minimum gas of previous tx --- ui/app/components/pending-tx.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 5b1b367c6..51e57dcd2 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -38,6 +38,14 @@ PendingTx.prototype.render = function () { const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} + // Allow retry txs + const { lastGasPrice } = txMeta + let forceGasMin + if (lastGasPrice) { + const stripped = ethUtil.stripHexPrefix(lastGasPrice) + forceGasMin = new BN(stripped, 16).add(MIN_GAS_PRICE_BN) + } + // Account Details const address = txParams.from || props.selectedAddress const identity = props.identities[address] || { address: address } @@ -199,7 +207,7 @@ PendingTx.prototype.render = function () { precision: 9, scale: 9, suffix: 'GWEI', - min: MIN_GAS_PRICE_BN, + min: forceGasMin || MIN_GAS_PRICE_BN, style: { position: 'relative', top: '5px', -- cgit From b9f2f8c2a78332a2522d49baedf25e894273ef38 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Thu, 7 Dec 2017 00:01:11 -0500 Subject: Show retry button on submitted transactions greater than 30 seconds, add hover styling --- ui/app/components/transaction-list-item.js | 8 +++++++- ui/app/css/index.css | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/transaction-list-item.js b/ui/app/components/transaction-list-item.js index fa6c5915d..42ef665b1 100644 --- a/ui/app/components/transaction-list-item.js +++ b/ui/app/components/transaction-list-item.js @@ -28,6 +28,12 @@ function TransactionListItem () { Component.call(this) } +TransactionListItem.prototype.showRetryButton = function () { + const { transaction = {} } = this.props + const { status, time } = transaction + return status === 'submitted' && Date.now() - time > 30000 +} + TransactionListItem.prototype.render = function () { const { transaction, network, conversionRate, currentCurrency } = this.props const { status } = transaction @@ -114,7 +120,7 @@ TransactionListItem.prototype.render = function () { }) : h('.flex-column'), ]), - transaction.status === 'submitted' && h('.transition-list-item__retry', { + this.showRetryButton() && h('.transition-list-item__retry.grow-on-hover', { onClick: event => { event.stopPropagation() this.resubmit() diff --git a/ui/app/css/index.css b/ui/app/css/index.css index 0630c4c12..c0bf18c23 100644 --- a/ui/app/css/index.css +++ b/ui/app/css/index.css @@ -108,6 +108,10 @@ button:not([disabled]):active, input[type="submit"]:not([disabled]):active { transform: scale(0.95); } +.grow-on-hover:hover { + transform: scale(1.05); +} + a { text-decoration: none; color: inherit; -- cgit From ec6c3c33bdbe2d90dc71649d0cc5fb3c07d96af7 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 5 Dec 2017 13:11:59 -0330 Subject: Merge branch 'master' into NewUI-flat-merge-with-master --- ui/app/first-time/init-menu.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/first-time/init-menu.js b/ui/app/first-time/init-menu.js index cc7c51bd3..b4587f1ee 100644 --- a/ui/app/first-time/init-menu.js +++ b/ui/app/first-time/init-menu.js @@ -8,6 +8,8 @@ const actions = require('../actions') const Tooltip = require('../components/tooltip') const getCaretCoordinates = require('textarea-caret') +let isSubmitting = false + module.exports = connect(mapStateToProps)(InitializeMenuScreen) inherits(InitializeMenuScreen, Component) @@ -164,7 +166,10 @@ InitializeMenuScreen.prototype.createNewVaultAndKeychain = function () { return } - this.props.dispatch(actions.createNewVaultAndKeychain(password)) + if (!isSubmitting) { + isSubmitting = true + this.props.dispatch(actions.createNewVaultAndKeychain(password)) + } } InitializeMenuScreen.prototype.inputChanged = function (event) { -- cgit From 2e9137dddd4abd07cc45caa670f09bdc9559bbbb Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 16 Nov 2017 14:44:25 -0330 Subject: Update max amount behaviour to meet new specs. --- ui/app/actions.js | 9 +++++++++ ui/app/components/customize-gas-modal/index.js | 22 +++++++++++++++++++++- ui/app/components/send/send-v2-container.js | 1 + ui/app/reducers/metamask.js | 9 +++++++++ ui/app/selectors.js | 5 +++++ ui/app/send-v2.js | 24 ++++++++++-------------- 6 files changed, 55 insertions(+), 15 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index e79f4373e..326c361cd 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -149,6 +149,7 @@ var actions = { UPDATE_SEND_AMOUNT: 'UPDATE_SEND_AMOUNT', UPDATE_SEND_MEMO: 'UPDATE_SEND_MEMO', UPDATE_SEND_ERRORS: 'UPDATE_SEND_ERRORS', + UPDATE_MAX_MODE: 'UPDATE_MAX_MODE', UPDATE_SEND: 'UPDATE_SEND', CLEAR_SEND: 'CLEAR_SEND', updateGasLimit, @@ -160,6 +161,7 @@ var actions = { updateSendAmount, updateSendMemo, updateSendErrors, + setMaxModeTo, updateSend, clearSend, setSelectedAddress, @@ -637,6 +639,13 @@ function updateSendErrors (error) { } } +function setMaxModeTo (bool) { + return { + type: actions.UPDATE_MAX_MODE, + value: bool, + } +} + function updateSend (newSend) { return { type: actions.UPDATE_SEND, diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 485dacf90..826d2cd4b 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -5,6 +5,8 @@ const connect = require('react-redux').connect const actions = require('../../actions') const GasModalCard = require('./gas-modal-card') +const ethUtil = require('ethereumjs-util') + const { MIN_GAS_PRICE_DEC, MIN_GAS_LIMIT_DEC, @@ -19,6 +21,7 @@ const { conversionUtil, multiplyCurrencies, conversionGreaterThan, + subtractCurrencies, } = require('../../conversion-util') const { @@ -30,6 +33,7 @@ const { getSendFrom, getCurrentAccountWithSendEtherInfo, getSelectedTokenToFiatRate, + getSendMaxModeState, } = require('../../selectors') function mapStateToProps (state) { @@ -42,6 +46,7 @@ function mapStateToProps (state) { gasLimit: getGasLimit(state), conversionRate, amount: getSendAmount(state), + maxModeOn: getSendMaxModeState(state), balance: currentAccount.balance, primaryCurrency: selectedToken && selectedToken.symbol, selectedToken, @@ -55,6 +60,7 @@ function mapDispatchToProps (dispatch) { updateGasPrice: newGasPrice => dispatch(actions.updateGasPrice(newGasPrice)), updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)), updateGasTotal: newGasTotal => dispatch(actions.updateGasTotal(newGasTotal)), + updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), } } @@ -93,8 +99,21 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { updateGasLimit, hideModal, updateGasTotal, + maxModeOn, + selectedToken, + balance, + updateSendAmount, } = this.props + if (maxModeOn && !selectedToken) { + const maxAmount = subtractCurrencies( + ethUtil.addHexPrefix(balance), + ethUtil.addHexPrefix(gasTotal), + { toNumericBase: 'hex' } + ) + updateSendAmount(maxAmount) + } + updateGasPrice(gasPrice) updateGasLimit(gasLimit) updateGasTotal(gasTotal) @@ -112,12 +131,13 @@ CustomizeGasModal.prototype.validate = function ({ gasTotal, gasLimit }) { selectedToken, amountConversionRate, conversionRate, + maxModeOn, } = this.props let error = null const balanceIsSufficient = isBalanceSufficient({ - amount: selectedToken ? '0' : amount, + amount: selectedToken || maxModeOn ? '0' : amount, gasTotal, balance, selectedToken, diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 4451a6113..655de8897 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -78,5 +78,6 @@ function mapDispatchToProps (dispatch) { goHome: () => dispatch(actions.goHome()), clearSend: () => dispatch(actions.clearSend()), backToConfirmScreen: editingTransactionId => dispatch(actions.showConfTxPage({ id: editingTransactionId })), + setMaxModeTo: bool => dispatch(actions.setMaxModeTo(bool)), } } diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index fb53bbaef..98207f23b 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -33,6 +33,7 @@ function reduceMetamask (state, action) { amount: '0x0', memo: '', errors: {}, + maxModeOn: false, editingTransactionId: null, }, coinOptions: {}, @@ -258,6 +259,14 @@ function reduceMetamask (state, action) { }, }) + case actions.UPDATE_MAX_MODE: + return extend(metamaskState, { + send: { + ...metamaskState.send, + maxModeOn: action.value, + }, + }) + case actions.UPDATE_SEND: return extend(metamaskState, { send: { diff --git a/ui/app/selectors.js b/ui/app/selectors.js index a5f9a75d8..f891f70c0 100644 --- a/ui/app/selectors.js +++ b/ui/app/selectors.js @@ -24,6 +24,7 @@ const selectors = { getSendAmount, getSelectedTokenToFiatRate, getSelectedTokenContract, + getSendMaxModeState, } module.exports = selectors @@ -135,6 +136,10 @@ function getSendAmount (state) { return state.metamask.send.amount } +function getSendMaxModeState (state) { + return state.metamask.send.maxModeOn +} + function getCurrentCurrency (state) { return state.metamask.currentCurrency } diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 788ae87b4..e1b88f0db 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -13,8 +13,6 @@ const GasFeeDisplay = require('./components/send/gas-fee-display-v2') const { MIN_GAS_TOTAL, - MIN_GAS_PRICE_HEX, - MIN_GAS_LIMIT_HEX, } = require('./components/send/send-constants') const { @@ -313,8 +311,9 @@ SendTransactionScreen.prototype.renderToRow = function () { SendTransactionScreen.prototype.handleAmountChange = function (value) { const amount = value - const { updateSendAmount } = this.props + const { updateSendAmount, setMaxModeTo } = this.props + setMaxModeTo(false) this.validateAmount(amount) updateSendAmount(amount) } @@ -324,11 +323,9 @@ SendTransactionScreen.prototype.setAmountToMax = function () { from: { balance }, updateSendAmount, updateSendErrors, - updateGasPrice, - updateGasLimit, - updateGasTotal, tokenBalance, selectedToken, + gasTotal, } = this.props const { decimals } = selectedToken || {} const multiplier = Math.pow(10, Number(decimals || 0)) @@ -337,16 +334,12 @@ SendTransactionScreen.prototype.setAmountToMax = function () { ? multiplyCurrencies(tokenBalance, multiplier, {toNumericBase: 'hex'}) : subtractCurrencies( ethUtil.addHexPrefix(balance), - ethUtil.addHexPrefix(MIN_GAS_TOTAL), + ethUtil.addHexPrefix(gasTotal), { toNumericBase: 'hex' } ) updateSendErrors({ amount: null }) - if (!selectedToken) { - updateGasPrice(MIN_GAS_PRICE_HEX) - updateGasLimit(MIN_GAS_LIMIT_HEX) - updateGasTotal(MIN_GAS_TOTAL) - } + updateSendAmount(maxAmount) } @@ -407,19 +400,22 @@ SendTransactionScreen.prototype.renderAmountRow = function () { amountConversionRate, errors, amount, + setMaxModeTo, + maxModeOn, } = this.props return h('div.send-v2__form-row', [ - h('div.send-v2__form-label', [ + h('div.send-v2__form-label', [ 'Amount:', this.renderErrorMessage('amount'), !errors.amount && h('div.send-v2__amount-max', { onClick: (event) => { event.preventDefault() + setMaxModeTo(true) this.setAmountToMax() }, - }, [ 'Max' ]), + }, [ !maxModeOn ? 'Max' : '' ]), ]), h('div.send-v2__form-field', [ -- cgit From c82fd990aafd72ede0c08d2820c0c1f1db6bfa81 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 7 Dec 2017 04:02:11 -0500 Subject: Add 10% price bump to retry attempts. Turns out geth requires at least a 10% price bump to replace txs: https://github.com/ethereum/go-ethereum/blob/9619a610248e9630968ba1d9be8e214b645c9c55/core/tx_pool.go#L133 --- ui/app/components/pending-tx.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/pending-tx.js b/ui/app/components/pending-tx.js index 51e57dcd2..32d54902e 100644 --- a/ui/app/components/pending-tx.js +++ b/ui/app/components/pending-tx.js @@ -43,7 +43,9 @@ PendingTx.prototype.render = function () { let forceGasMin if (lastGasPrice) { const stripped = ethUtil.stripHexPrefix(lastGasPrice) - forceGasMin = new BN(stripped, 16).add(MIN_GAS_PRICE_BN) + const lastGas = new BN(stripped, 16) + const priceBump = lastGas.divn('10') + forceGasMin = lastGas.add(priceBump) } // Account Details -- cgit From bfec077d798aea7b2869b3ff0d292243eec60da5 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 8 Dec 2017 13:09:53 -0330 Subject: Fixes the cancel button in the buy screen to take the user home. --- ui/app/components/coinbase-form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/coinbase-form.js b/ui/app/components/coinbase-form.js index f44d86045..f70208625 100644 --- a/ui/app/components/coinbase-form.js +++ b/ui/app/components/coinbase-form.js @@ -40,7 +40,7 @@ CoinbaseForm.prototype.render = function () { }, 'Continue to Coinbase'), h('button.btn-red', { - onClick: () => props.dispatch(actions.backTobuyView(props.accounts.address)), + onClick: () => props.dispatch(actions.goHome()), }, 'Cancel'), ]), ]) -- cgit From d110c916a4dde947dcfdc610aaadf9fba251449a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 12 Dec 2017 09:47:51 -0800 Subject: Show watched tokens with no balance --- ui/app/components/token-list.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'ui') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 998ec901d..149733b89 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -194,10 +194,7 @@ TokenList.prototype.componentWillUpdate = function (nextProps) { } TokenList.prototype.updateBalances = function (tokens) { - const heldTokens = tokens.filter(token => { - return token.balance !== '0' && token.string !== '0.000' - }) - this.setState({ tokens: heldTokens, isLoading: false }) + this.setState({ tokens, isLoading: false }) } TokenList.prototype.componentWillUnmount = function () { -- cgit From 05c6789030791bd1b46434cf89c1817db37e8f38 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 8 Dec 2017 21:18:08 -0330 Subject: Adds button for opening app in main browser window in extension. --- ui/app/components/tx-view.js | 5 +++++ ui/app/css/itcss/components/newui-sections.scss | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'ui') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index ebef22680..832f8e56a 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -107,6 +107,7 @@ TxView.prototype.render = function () { h('div.flex-row.phone-visible', { style: { margin: '1em 0.9em', + justifyContent: 'space-between', alignItems: 'center', }, }, [ @@ -139,6 +140,10 @@ TxView.prototype.render = function () { identity.name, ]), + h('div.open-in-browser', { + onClick: () => global.platform.openExtensionInBrowser(), + }, [h('img', { src: 'images/open.svg' })]) + ]), this.renderHeroBalance(), diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/app/css/itcss/components/newui-sections.scss index 43a59c4da..61dfbd176 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/app/css/itcss/components/newui-sections.scss @@ -38,6 +38,10 @@ $wallet-view-bg: $wild-sand; } } +.open-in-browser { + cursor: pointer; +} + // wallet view and sidebar .wallet-view { -- cgit From 4b654669e692665aba88a14cb5804370dbfd4a80 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 8 Dec 2017 21:52:31 -0330 Subject: Hide open in browser button on mobile (but still show on extension); adds a function to detect if viewing with mobile browser. --- ui/app/components/tx-view.js | 5 +++-- ui/app/select-app.js | 1 - ui/lib/is-mobile-browser.js | 12 ++++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 ui/lib/is-mobile-browser.js (limited to 'ui') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 832f8e56a..bd52ac4c2 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -3,6 +3,7 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits +const isMobileBrowser = require('../../lib/is-mobile-browser') const actions = require('../actions') const selectors = require('../selectors') @@ -140,9 +141,9 @@ TxView.prototype.render = function () { identity.name, ]), - h('div.open-in-browser', { + !isMobileBrowser() && h('div.open-in-browser', { onClick: () => global.platform.openExtensionInBrowser(), - }, [h('img', { src: 'images/open.svg' })]) + }, [h('img', { src: 'images/open.svg' })]), ]), diff --git a/ui/app/select-app.js b/ui/app/select-app.js index ffa31b767..3ea93ced3 100644 --- a/ui/app/select-app.js +++ b/ui/app/select-app.js @@ -41,7 +41,6 @@ SelectedApp.prototype.componentWillReceiveProps = function (nextProps) { SelectedApp.prototype.render = function () { const { betaUI } = this.props - const { autoAdd } = this.state const Selected = betaUI ? App : OldApp return h(Selected) } diff --git a/ui/lib/is-mobile-browser.js b/ui/lib/is-mobile-browser.js new file mode 100644 index 000000000..8609ed3b1 --- /dev/null +++ b/ui/lib/is-mobile-browser.js @@ -0,0 +1,12 @@ +/* eslint-disable */ + +// See https://stackoverflow.com/questions/11381673/detecting-a-mobile-browser +// Checks whether the user is viewing the app through mobile +// isMobileBrowser :: () => Bool +const isMobileBrowser = () => { + let check = false; + (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); + return check; +}; + +module.exports = isMobileBrowser \ No newline at end of file -- cgit From 57c91435a7357165441252acfffcdaff6e54e422 Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 12 Dec 2017 16:21:05 -0330 Subject: Substitute isMascara check for explicit check if user is on mobile browser. --- ui/app/components/tx-view.js | 3 ++- ui/lib/is-mobile-browser.js | 12 ------------ 2 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 ui/lib/is-mobile-browser.js (limited to 'ui') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index bd52ac4c2..0f8a54a74 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -15,6 +15,7 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(TxView) function mapStateToProps (state) { const sidebarOpen = state.appState.sidebarOpen + const isMascara = state.appState.isMascara const identities = state.metamask.identities const accounts = state.metamask.accounts @@ -141,7 +142,7 @@ TxView.prototype.render = function () { identity.name, ]), - !isMobileBrowser() && h('div.open-in-browser', { + !isMascara && h('div.open-in-browser', { onClick: () => global.platform.openExtensionInBrowser(), }, [h('img', { src: 'images/open.svg' })]), diff --git a/ui/lib/is-mobile-browser.js b/ui/lib/is-mobile-browser.js deleted file mode 100644 index 8609ed3b1..000000000 --- a/ui/lib/is-mobile-browser.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-disable */ - -// See https://stackoverflow.com/questions/11381673/detecting-a-mobile-browser -// Checks whether the user is viewing the app through mobile -// isMobileBrowser :: () => Bool -const isMobileBrowser = () => { - let check = false; - (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera); - return check; -}; - -module.exports = isMobileBrowser \ No newline at end of file -- cgit From 515437a4c956e47a5f1d4522715a9021e08d3408 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 12 Dec 2017 12:22:22 -0800 Subject: Fix isMascara and update yarn.lock --- ui/app/components/tx-view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 0f8a54a74..e42a20c85 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -3,7 +3,6 @@ const connect = require('react-redux').connect const h = require('react-hyperscript') const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits -const isMobileBrowser = require('../../lib/is-mobile-browser') const actions = require('../actions') const selectors = require('../selectors') @@ -33,6 +32,7 @@ function mapStateToProps (state) { selectedToken: selectors.getSelectedToken(state), identity, network, + isMascara, } } @@ -100,7 +100,7 @@ TxView.prototype.renderButtons = function () { } TxView.prototype.render = function () { - const { selectedAddress, identity, network } = this.props + const { selectedAddress, identity, network, isMascara } = this.props return h('div.tx-view.flex-column', { style: {}, -- cgit From 4e0485938a84f665aef466ef34e90299c5863ff4 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 8 Dec 2017 12:36:32 -0330 Subject: Fix height of login screen --- ui/app/app.js | 52 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) (limited to 'ui') diff --git a/ui/app/app.js b/ui/app/app.js index 88a5c8458..1f40eccbe 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -116,41 +116,39 @@ App.prototype.render = function () { log.debug('Main ui render function') return ( - h('.new-ui', [ - h('.flex-column.full-height', { - style: { - overflowX: 'hidden', - position: 'relative', - alignItems: 'center', - }, - }, [ + h('.flex-column.full-height', { + style: { + overflowX: 'hidden', + position: 'relative', + alignItems: 'center', + }, + }, [ - // global modal - h(Modal, {}, []), + // global modal + h(Modal, {}, []), - // app bar - this.renderAppBar(), + // app bar + this.renderAppBar(), - // sidebar - this.renderSidebar(), + // sidebar + this.renderSidebar(), - // network dropdown - h(NetworkDropdown, { - provider: this.props.provider, - frequentRpcList: this.props.frequentRpcList, - }, []), + // network dropdown + h(NetworkDropdown, { + provider: this.props.provider, + frequentRpcList: this.props.frequentRpcList, + }, []), - h(AccountMenu), + h(AccountMenu), - (isLoading || isLoadingNetwork) && h(Loading, { - loadingMessage: loadMessage, - }), + (isLoading || isLoadingNetwork) && h(Loading, { + loadingMessage: loadMessage, + }), - // this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), + // this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), - // content - this.renderPrimary(), - ]), + // content + this.renderPrimary(), ]) ) } -- cgit From 339eb7d1a687f141e822c745c568063783d44f15 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 13 Dec 2017 02:54:41 -0330 Subject: Fix edit to field bug. (#2738) --- ui/app/components/pending-tx/confirm-send-token.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index cc2df8299..727cd260b 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -67,15 +67,15 @@ function mapDispatchToProps (dispatch, ownProps) { const { txParams, id } = txMeta const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) const { params = [] } = tokenData - const { value } = params[1] || {} - const amount = conversionUtil(value, { + const { value: to } = params[0] || {} + const { value: tokenAmountInDec } = params[1] || {} + const tokenAmountInHex = conversionUtil(tokenAmountInDec, { fromNumericBase: 'dec', toNumericBase: 'hex', }) const { gas: gasLimit, gasPrice, - to, } = txParams dispatch(actions.setSelectedToken(address)) dispatch(actions.updateSend({ @@ -83,7 +83,7 @@ function mapDispatchToProps (dispatch, ownProps) { gasPrice, gasTotal: null, to, - amount, + amount: tokenAmountInHex, errors: { to: null, amount: null }, editingTransactionId: id, })) @@ -446,10 +446,11 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { amount, gasLimit: gas, gasPrice, + to, }, } = props - const { txParams: { from, to } } = txData + const { txParams: { from, to: tokenAddress } } = txData const tokenParams = { from: ethUtil.addHexPrefix(from), @@ -465,7 +466,7 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { txData.txParams = { ...tokenParams, - to: ethUtil.addHexPrefix(to), + to: ethUtil.addHexPrefix(tokenAddress), memo: memo && ethUtil.addHexPrefix(memo), data, } -- cgit From 0feb5b210b81533fc25c4760ce33876b4c749247 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 14:19:13 -0330 Subject: Hides the sidebar after the an account menu actions changes the screen behind the sidebar. --- ui/app/components/account-menu/index.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'ui') diff --git a/ui/app/components/account-menu/index.js b/ui/app/components/account-menu/index.js index a9f075ec7..286a3b587 100644 --- a/ui/app/components/account-menu/index.js +++ b/ui/app/components/account-menu/index.js @@ -28,27 +28,33 @@ function mapDispatchToProps (dispatch) { toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()), showAccountDetail: address => { dispatch(actions.showAccountDetail(address)) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, lockMetamask: () => { dispatch(actions.lockMetamask()) dispatch(actions.displayWarning(null)) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, showConfigPage: () => { dispatch(actions.showConfigPage()) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, showNewAccountModal: () => { dispatch(actions.showModal({ name: 'NEW_ACCOUNT' })) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, showImportPage: () => { dispatch(actions.showImportPage()) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, showInfoPage: () => { dispatch(actions.showInfoPage()) + dispatch(actions.hideSidebar()) dispatch(actions.toggleAccountMenu()) }, } -- cgit From 109e4e5d96e31b52fcfdb22620bff113107d000c Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 19 Dec 2017 14:02:32 -0330 Subject: Hide fiat values on account details screen when eth/token value is 0. --- ui/app/components/balance-component.js | 3 ++- ui/app/components/token-cell.js | 4 +++- ui/app/components/tx-list-item.js | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'ui') diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index d14aa675f..50007ce14 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -94,7 +94,8 @@ BalanceComponent.prototype.renderFiatValue = function (formattedBalance) { } BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatSuffix, fiatPrefix) { - if (fiatDisplayNumber === 'N/A') return null + const shouldNotRenderFiat = fiatDisplayNumber === 'N/A' || Number(fiatDisplayNumber) === 0 + if (shouldNotRenderFiat) return null return h('div.fiat-amount', { style: {}, diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index b40c0ec0d..677b66830 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -86,7 +86,9 @@ TokenCell.prototype.render = function () { numberOfDecimals: 2, conversionRate: currentTokenToFiatRate, }) - formattedFiat = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}` + formattedFiat = currentTokenInFiat.toString() === '0' + ? '' + : `${currentTokenInFiat} ${currentCurrency.toUpperCase()}` } const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 4e76147a1..8a9253d4d 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -170,6 +170,7 @@ TxListItem.prototype.getSendTokenTotal = async function () { TxListItem.prototype.render = function () { const { transactionStatus, + transactionAmount, onClick, transActionId, dateString, @@ -177,6 +178,7 @@ TxListItem.prototype.render = function () { className, } = this.props const { total, fiatTotal } = this.state + const showFiatTotal = transactionAmount !== '0x0' && fiatTotal return h(`div${className || ''}`, { key: transActionId, @@ -238,7 +240,7 @@ TxListItem.prototype.render = function () { }), }, total), - fiatTotal && h('span.tx-list-fiat-value', fiatTotal), + showFiatTotal && h('span.tx-list-fiat-value', fiatTotal), ]), ]), -- cgit From bccbf14b39ab2b1670c9c30b276404fe4f949cd7 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 20 Dec 2017 14:52:50 -0330 Subject: [NewUI] Hide UI toggle in mascara (#2772) * Hides old-UI on mascara. * Improve code clarity in select-app.js --- ui/app/actions.js | 7 ++----- ui/app/select-app.js | 25 +++++++++++++++---------- ui/app/settings.js | 8 +++++--- 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index ed0518184..e694152a2 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -1523,10 +1523,7 @@ function updateTokenExchangeRate (token = '') { } } -function setFeatureFlag (feature, activated) { - const notificationType = activated - ? 'BETA_UI_NOTIFICATION_MODAL' - : 'OLD_UI_NOTIFICATION_MODAL' +function setFeatureFlag (feature, activated, notificationType) { return (dispatch) => { dispatch(actions.showLoadingIndication()) return new Promise((resolve, reject) => { @@ -1537,7 +1534,7 @@ function setFeatureFlag (feature, activated) { reject(err) } dispatch(actions.updateFeatureFlags(updatedFeatureFlags)) - dispatch(actions.showModal({ name: notificationType })) + notificationType && dispatch(actions.showModal({ name: notificationType })) resolve(updatedFeatureFlags) }) }) diff --git a/ui/app/select-app.js b/ui/app/select-app.js index 3ea93ced3..a51182f47 100644 --- a/ui/app/select-app.js +++ b/ui/app/select-app.js @@ -12,35 +12,40 @@ function mapStateToProps (state) { betaUI: state.metamask.featureFlags.betaUI, autoAdd: autoAddToBetaUI(state), isUnlocked: state.metamask.isUnlocked, + isMascara: state.metamask.isMascara, } } function mapDispatchToProps (dispatch) { return { - setFeatureFlagToBeta: () => dispatch(setFeatureFlag('betaUI', true)), + setFeatureFlagWithModal: () => dispatch(setFeatureFlag('betaUI', true, 'BETA_UI_NOTIFICATION_MODAL')), + setFeatureFlagWithoutModal: () => dispatch(setFeatureFlag('betaUI', true)), } } module.exports = connect(mapStateToProps, mapDispatchToProps)(SelectedApp) inherits(SelectedApp, Component) function SelectedApp () { - this.state = { - autoAdd: false, - } Component.call(this) } SelectedApp.prototype.componentWillReceiveProps = function (nextProps) { - const { isUnlocked, setFeatureFlagToBeta } = this.props + const { + isUnlocked, + setFeatureFlagWithModal, + setFeatureFlagWithoutModal, + isMascara, + } = this.props - if (!isUnlocked && nextProps.isUnlocked && nextProps.autoAdd) { - this.setState({ autoAdd: nextProps.autoAdd }) - setFeatureFlagToBeta() + if (isMascara) { + setFeatureFlagWithoutModal() + } else if (!isUnlocked && nextProps.isUnlocked && (nextProps.autoAdd)) { + setFeatureFlagWithModal() } } SelectedApp.prototype.render = function () { - const { betaUI } = this.props - const Selected = betaUI ? App : OldApp + const { betaUI, isMascara } = this.props + const Selected = betaUI || isMascara ? App : OldApp return h(Selected) } diff --git a/ui/app/settings.js b/ui/app/settings.js index ca7535d26..74b282a98 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -250,7 +250,7 @@ class Settings extends Component { } renderSettingsContent () { - const { warning } = this.props + const { warning, isMascara } = this.props return ( h('div.settings__content', [ @@ -261,7 +261,7 @@ class Settings extends Component { this.renderNewRpcUrl(), this.renderStateLogs(), this.renderSeedWords(), - this.renderOldUI(), + !isMascara && this.renderOldUI(), ]) ) } @@ -386,12 +386,14 @@ Settings.propTypes = { setFeatureFlagToBeta: PropTypes.func, warning: PropTypes.string, goHome: PropTypes.func, + isMascara: PropTypes.bool, } const mapStateToProps = state => { return { metamask: state.metamask, warning: state.appState.warning, + isMascara: state.metamask.isMascara, } } @@ -403,7 +405,7 @@ const mapDispatchToProps = dispatch => { displayWarning: warning => dispatch(actions.displayWarning(warning)), revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()), setUseBlockie: value => dispatch(actions.setUseBlockie(value)), - setFeatureFlagToBeta: () => dispatch(actions.setFeatureFlag('betaUI', false)), + setFeatureFlagToBeta: () => dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')), } } -- cgit From 1f1fc2c49ecbb5c6a0a1d925d5c02cf48f795b2f Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 19 Dec 2017 11:16:11 -0330 Subject: Canceled, edited transactions show edited amount. --- ui/app/actions.js | 19 +++++++++++++++++++ ui/app/components/pending-tx/confirm-send-ether.js | 9 ++++++++- ui/app/components/pending-tx/confirm-send-token.js | 9 ++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index e694152a2..9d3d7184e 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -126,6 +126,7 @@ var actions = { signTx: signTx, signTokenTx: signTokenTx, updateAndApproveTx, + updateAndCancelTx, cancelTx: cancelTx, completedTx: completedTx, txError: txError, @@ -710,6 +711,24 @@ function updateAndApproveTx (txData) { } } +function updateAndCancelTx (txData) { + log.info('actions: updateAndCancelTx: ' + JSON.stringify(txData)) + return (dispatch) => { + log.debug(`actions calling background.updateAndCancelTx`) + background.updateAndCancelTransaction(txData, (err) => { + dispatch(actions.hideLoadingIndication()) + dispatch(actions.updateTransactionParams(txData.id, txData.txParams)) + dispatch(actions.clearSend()) + if (err) { + dispatch(actions.txError(err)) + dispatch(actions.goHome()) + return log.error(err.message) + } + dispatch(actions.completedTx(txData.id)) + }) + } +} + function completedTx (id) { return { type: actions.COMPLETED_TX, diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 1264da153..01195502e 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -55,6 +55,7 @@ function mapDispatchToProps (dispatch) { dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), + updateAndCancelTx: txMeta => dispatch(actions.updateAndCancelTx(txMeta)), } } @@ -421,7 +422,13 @@ ConfirmSendEther.prototype.onSubmit = function (event) { ConfirmSendEther.prototype.cancel = function (event, txMeta) { event.preventDefault() - this.props.cancelTransaction(txMeta) + const { send, updateAndCancelTx, cancelTransaction } = this.props + + if (send.editingTransactionId) { + updateAndCancelTx(txMeta) + } else { + cancelTransaction(txMeta) + } } ConfirmSendEther.prototype.checkValidity = function () { diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 727cd260b..e6ce3f6e6 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -89,6 +89,7 @@ function mapDispatchToProps (dispatch, ownProps) { })) dispatch(actions.showSendTokenPage()) }, + updateAndCancelTx: txMeta => dispatch(actions.updateAndCancelTx(txMeta)), } } @@ -415,7 +416,13 @@ ConfirmSendToken.prototype.onSubmit = function (event) { ConfirmSendToken.prototype.cancel = function (event, txMeta) { event.preventDefault() - this.props.cancelTransaction(txMeta) + const { send, updateAndCancelTx, cancelTransaction } = this.props + + if (send.editingTransactionId) { + updateAndCancelTx(txMeta) + } else { + cancelTransaction(txMeta) + } } ConfirmSendToken.prototype.checkValidity = function () { -- cgit From bf4043c59bb67ea93599207d91cb7a4f4426e75f Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 13:47:16 -0330 Subject: Adds updateTransaction to background and used it to update after editing in send-v2. --- ui/app/actions.js | 22 +++--- ui/app/components/pending-tx/confirm-send-ether.js | 29 +------- ui/app/components/pending-tx/confirm-send-token.js | 42 +----------- ui/app/components/send/send-v2-container.js | 2 + ui/app/conf-tx.js | 2 +- ui/app/send-v2.js | 78 +++++++++++++++++----- 6 files changed, 80 insertions(+), 95 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index 9d3d7184e..ef8a5ec46 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -125,8 +125,8 @@ var actions = { sendTx: sendTx, signTx: signTx, signTokenTx: signTokenTx, + updateTransaction, updateAndApproveTx, - updateAndCancelTx, cancelTx: cancelTx, completedTx: completedTx, txError: txError, @@ -693,29 +693,28 @@ function signTokenTx (tokenAddress, toAddress, amount, txData) { } } -function updateAndApproveTx (txData) { - log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData)) +function updateTransaction (txData) { + log.info('actions: updateTx: ' + JSON.stringify(txData)) return (dispatch) => { - log.debug(`actions calling background.updateAndApproveTx`) - background.updateAndApproveTransaction(txData, (err) => { + log.debug(`actions calling background.updateTx`) + background.updateTransaction(txData, (err) => { dispatch(actions.hideLoadingIndication()) dispatch(actions.updateTransactionParams(txData.id, txData.txParams)) - dispatch(actions.clearSend()) if (err) { dispatch(actions.txError(err)) dispatch(actions.goHome()) return log.error(err.message) } - dispatch(actions.completedTx(txData.id)) + dispatch(actions.showConfTxPage({ id: txData.id })) }) } } -function updateAndCancelTx (txData) { - log.info('actions: updateAndCancelTx: ' + JSON.stringify(txData)) +function updateAndApproveTx (txData) { + log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData)) return (dispatch) => { - log.debug(`actions calling background.updateAndCancelTx`) - background.updateAndCancelTransaction(txData, (err) => { + log.debug(`actions calling background.updateAndApproveTx`) + background.updateAndApproveTransaction(txData, (err) => { dispatch(actions.hideLoadingIndication()) dispatch(actions.updateTransactionParams(txData.id, txData.txParams)) dispatch(actions.clearSend()) @@ -773,6 +772,7 @@ function cancelTx (txData) { return (dispatch) => { log.debug(`background.cancelTransaction`) background.cancelTransaction(txData.id, () => { + dispatch(actions.clearSend()) dispatch(actions.completedTx(txData.id)) }) } diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 01195502e..566224864 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -55,7 +55,6 @@ function mapDispatchToProps (dispatch) { dispatch(actions.showSendPage()) }, cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), - updateAndCancelTx: txMeta => dispatch(actions.updateAndCancelTx(txMeta)), } } @@ -422,13 +421,9 @@ ConfirmSendEther.prototype.onSubmit = function (event) { ConfirmSendEther.prototype.cancel = function (event, txMeta) { event.preventDefault() - const { send, updateAndCancelTx, cancelTransaction } = this.props + const { cancelTransaction } = this.props - if (send.editingTransactionId) { - updateAndCancelTx(txMeta) - } else { - cancelTransaction(txMeta) - } + cancelTransaction(txMeta) } ConfirmSendEther.prototype.checkValidity = function () { @@ -452,26 +447,6 @@ ConfirmSendEther.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) - if (props.send.editingTransactionId) { - const { - send: { - memo, - amount: value, - gasLimit: gas, - gasPrice, - }, - } = props - const { txParams: { from, to } } = txData - txData.txParams = { - from: ethUtil.addHexPrefix(from), - to: ethUtil.addHexPrefix(to), - memo: memo && ethUtil.addHexPrefix(memo), - value: ethUtil.addHexPrefix(value), - gas: ethUtil.addHexPrefix(gas), - gasPrice: ethUtil.addHexPrefix(gasPrice), - } - } - // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData } diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index e6ce3f6e6..a07835911 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -89,7 +89,6 @@ function mapDispatchToProps (dispatch, ownProps) { })) dispatch(actions.showSendTokenPage()) }, - updateAndCancelTx: txMeta => dispatch(actions.updateAndCancelTx(txMeta)), } } @@ -416,13 +415,9 @@ ConfirmSendToken.prototype.onSubmit = function (event) { ConfirmSendToken.prototype.cancel = function (event, txMeta) { event.preventDefault() - const { send, updateAndCancelTx, cancelTransaction } = this.props + const { send, cancelTransaction } = this.props - if (send.editingTransactionId) { - updateAndCancelTx(txMeta) - } else { - cancelTransaction(txMeta) - } + cancelTransaction(txMeta) } ConfirmSendToken.prototype.checkValidity = function () { @@ -446,39 +441,6 @@ ConfirmSendToken.prototype.gatherTxMeta = function () { const state = this.state const txData = clone(state.txData) || clone(props.txData) - if (props.send.editingTransactionId) { - const { - send: { - memo, - amount, - gasLimit: gas, - gasPrice, - to, - }, - } = props - - const { txParams: { from, to: tokenAddress } } = txData - - const tokenParams = { - from: ethUtil.addHexPrefix(from), - value: '0', - gas: ethUtil.addHexPrefix(gas), - gasPrice: ethUtil.addHexPrefix(gasPrice), - } - - const data = '0xa9059cbb' + Array.prototype.map.call( - ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), - x => ('00' + x.toString(16)).slice(-2) - ).join('') - - txData.txParams = { - ...tokenParams, - to: ethUtil.addHexPrefix(tokenAddress), - memo: memo && ethUtil.addHexPrefix(memo), - data, - } - } - // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) return txData } diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index 655de8897..ff7714e82 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -50,6 +50,7 @@ function mapStateToProps (state) { data, amountConversionRate: selectedToken ? tokenToFiatRate : conversionRate, tokenContract: getSelectedTokenContract(state), + unapprovedTxs: state.metamask.unapprovedTxs, } } @@ -64,6 +65,7 @@ function mapDispatchToProps (dispatch) { ), signTx: txParams => dispatch(actions.signTx(txParams)), updateAndApproveTx: txParams => dispatch(actions.updateAndApproveTx(txParams)), + updateTx: txData => dispatch(actions.updateTransaction(txData)), setSelectedAddress: address => dispatch(actions.setSelectedAddress(address)), addToAddressBook: address => dispatch(actions.addToAddressBook(address)), updateGasTotal: newTotal => dispatch(actions.updateGasTotal(newTotal)), diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index 9f273aaec..d71e4b35f 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -115,7 +115,7 @@ function currentTxView (opts) { log.info('rendering current tx view') const { txData } = opts const { txParams, msgParams } = txData - + console.log(`22222 currentTxView txData`, txData); if (txParams) { log.debug('txParams detected, rendering pending tx') return h(PendingTx, opts) diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index e1b88f0db..617211b20 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -2,6 +2,7 @@ const { inherits } = require('util') const PersistentForm = require('../lib/persistent-form') const h = require('react-hyperscript') +const ethAbi = require('ethereumjs-abi') const ethUtil = require('ethereumjs-util') const Identicon = require('./components/identicon') @@ -552,6 +553,47 @@ SendTransactionScreen.prototype.addToAddressBookIfNew = function (newAddress) { } } +SendTransactionScreen.prototype.getEditedTx = function () { + const { + from: {address: from}, + to, + amount, + gasLimit: gas, + gasPrice, + selectedToken, + editingTransactionId, + unapprovedTxs, + } = this.props + + const editingTx = unapprovedTxs[editingTransactionId] + + editingTx.txParams = { + from: ethUtil.addHexPrefix(from), + gas: ethUtil.addHexPrefix(gas), + gasPrice: ethUtil.addHexPrefix(gasPrice), + } + + if (selectedToken) { + const data = '0xa9059cbb' + Array.prototype.map.call( + ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), + x => ('00' + x.toString(16)).slice(-2) + ).join('') + + Object.assign(editingTx.txParams, { + value: ethUtil.addHexPrefix('0'), + to: ethUtil.addHexPrefix(selectedToken.address), + data, + }) + } else { + Object.assign(editingTx.txParams, { + value: ethUtil.addHexPrefix(amount), + to: ethUtil.addHexPrefix(to), + }) + } + + return editingTx +} + SendTransactionScreen.prototype.onSubmit = function (event) { event.preventDefault() const { @@ -562,10 +604,12 @@ SendTransactionScreen.prototype.onSubmit = function (event) { gasPrice, signTokenTx, signTx, + updateTx, selectedToken, editingTransactionId, errors: { amount: amountError, to: toError }, backToConfirmScreen, + unapprovedTxs, } = this.props const noErrors = !amountError && toError === null @@ -577,23 +621,25 @@ SendTransactionScreen.prototype.onSubmit = function (event) { this.addToAddressBookIfNew(to) if (editingTransactionId) { - backToConfirmScreen(editingTransactionId) - return - } + const editedTx = this.getEditedTx() - const txParams = { - from, - value: '0', - gas, - gasPrice, - } + updateTx(editedTx) + } else { - if (!selectedToken) { - txParams.value = amount - txParams.to = to - } + const txParams = { + from, + value: '0', + gas, + gasPrice, + } - selectedToken - ? signTokenTx(selectedToken.address, to, amount, txParams) - : signTx(txParams) + if (!selectedToken) { + txParams.value = amount + txParams.to = to + } + + selectedToken + ? signTokenTx(selectedToken.address, to, amount, txParams) + : signTx(txParams) + } } -- cgit From 5fe3c5aae6756f225edd0f8646ac0a23c264a81c Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 15:05:41 -0330 Subject: Lint fixes. --- ui/app/components/pending-tx/confirm-send-token.js | 3 +-- ui/app/components/send/send-v2-container.js | 1 - ui/app/conf-tx.js | 2 +- ui/app/send-v2.js | 2 -- 4 files changed, 2 insertions(+), 6 deletions(-) (limited to 'ui') diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index a07835911..aa4f29fb0 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -2,7 +2,6 @@ const Component = require('react').Component const { connect } = require('react-redux') const h = require('react-hyperscript') const inherits = require('util').inherits -const ethAbi = require('ethereumjs-abi') const tokenAbi = require('human-standard-token-abi') const abiDecoder = require('abi-decoder') abiDecoder.addABI(tokenAbi) @@ -415,7 +414,7 @@ ConfirmSendToken.prototype.onSubmit = function (event) { ConfirmSendToken.prototype.cancel = function (event, txMeta) { event.preventDefault() - const { send, cancelTransaction } = this.props + const { cancelTransaction } = this.props cancelTransaction(txMeta) } diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index ff7714e82..2d2ed4546 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -79,7 +79,6 @@ function mapDispatchToProps (dispatch) { updateSendErrors: newError => dispatch(actions.updateSendErrors(newError)), goHome: () => dispatch(actions.goHome()), clearSend: () => dispatch(actions.clearSend()), - backToConfirmScreen: editingTransactionId => dispatch(actions.showConfTxPage({ id: editingTransactionId })), setMaxModeTo: bool => dispatch(actions.setMaxModeTo(bool)), } } diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index d71e4b35f..9f273aaec 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -115,7 +115,7 @@ function currentTxView (opts) { log.info('rendering current tx view') const { txData } = opts const { txParams, msgParams } = txData - console.log(`22222 currentTxView txData`, txData); + if (txParams) { log.debug('txParams detected, rendering pending tx') return h(PendingTx, opts) diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 617211b20..1c0ff3aea 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -608,8 +608,6 @@ SendTransactionScreen.prototype.onSubmit = function (event) { selectedToken, editingTransactionId, errors: { amount: amountError, to: toError }, - backToConfirmScreen, - unapprovedTxs, } = this.props const noErrors = !amountError && toError === null -- cgit From 9ced63584bc93cf6ac82786dec0984b5022346ae Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 19:06:58 -0330 Subject: Add constanst for token transfer function signature. --- ui/app/components/send/send-constants.js | 3 +++ ui/app/send-v2.js | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'ui') diff --git a/ui/app/components/send/send-constants.js b/ui/app/components/send/send-constants.js index 9c240972f..b3ee0899a 100644 --- a/ui/app/components/send/send-constants.js +++ b/ui/app/components/send/send-constants.js @@ -20,6 +20,8 @@ const MIN_GAS_TOTAL = multiplyCurrencies(MIN_GAS_LIMIT_HEX, MIN_GAS_PRICE_HEX, { multiplierBase: 16, }) +const TOKEN_TRANSFER_FUNCTION_SIGNATURE = '0xa9059cbb' + module.exports = { MIN_GAS_PRICE_GWEI, MIN_GAS_PRICE_HEX, @@ -27,4 +29,5 @@ module.exports = { MIN_GAS_LIMIT_HEX, MIN_GAS_LIMIT_DEC, MIN_GAS_TOTAL, + TOKEN_TRANSFER_FUNCTION_SIGNATURE, } diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 1c0ff3aea..cf9e709d4 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -14,6 +14,7 @@ const GasFeeDisplay = require('./components/send/gas-fee-display-v2') const { MIN_GAS_TOTAL, + TOKEN_TRANSFER_FUNCTION_SIGNATURE, } = require('./components/send/send-constants') const { @@ -574,7 +575,7 @@ SendTransactionScreen.prototype.getEditedTx = function () { } if (selectedToken) { - const data = '0xa9059cbb' + Array.prototype.map.call( + const data = TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]), x => ('00' + x.toString(16)).slice(-2) ).join('') -- cgit From e7e1b7a95180597308bd167bd4a152bbbf53ff21 Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Dec 2017 19:11:18 -0330 Subject: Clone transaction while editing instead of mutating object from state. --- ui/app/send-v2.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'ui') diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index cf9e709d4..b7f2e7277 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -566,12 +566,13 @@ SendTransactionScreen.prototype.getEditedTx = function () { unapprovedTxs, } = this.props - const editingTx = unapprovedTxs[editingTransactionId] - - editingTx.txParams = { - from: ethUtil.addHexPrefix(from), - gas: ethUtil.addHexPrefix(gas), - gasPrice: ethUtil.addHexPrefix(gasPrice), + const editingTx = { + ...unapprovedTxs[editingTransactionId], + txParams: { + from: ethUtil.addHexPrefix(from), + gas: ethUtil.addHexPrefix(gas), + gasPrice: ethUtil.addHexPrefix(gasPrice), + } } if (selectedToken) { -- cgit From 4acd48966edf2e6cf4ced6e3e0983a44dcb2ec13 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 21 Dec 2017 23:33:01 -0330 Subject: [NewUI] Fixes tests and sends user to NewUI after registering. (#2788) * Fixes tests and sends user to NewUI after registering. * Karma config? * Empty commit * Remove unneeded json state mock file. --- ui/app/select-app.js | 9 ++++++--- ui/app/send-v2.js | 2 +- ui/index.js | 1 - 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'ui') diff --git a/ui/app/select-app.js b/ui/app/select-app.js index a51182f47..0b837b547 100644 --- a/ui/app/select-app.js +++ b/ui/app/select-app.js @@ -13,6 +13,7 @@ function mapStateToProps (state) { autoAdd: autoAddToBetaUI(state), isUnlocked: state.metamask.isUnlocked, isMascara: state.metamask.isMascara, + firstTime: Object.keys(state.metamask.identities).length === 0, } } @@ -35,9 +36,10 @@ SelectedApp.prototype.componentWillReceiveProps = function (nextProps) { setFeatureFlagWithModal, setFeatureFlagWithoutModal, isMascara, + firstTime, } = this.props - if (isMascara) { + if (isMascara || firstTime) { setFeatureFlagWithoutModal() } else if (!isUnlocked && nextProps.isUnlocked && (nextProps.autoAdd)) { setFeatureFlagWithModal() @@ -45,7 +47,8 @@ SelectedApp.prototype.componentWillReceiveProps = function (nextProps) { } SelectedApp.prototype.render = function () { - const { betaUI, isMascara } = this.props - const Selected = betaUI || isMascara ? App : OldApp + const { betaUI, isMascara, firstTime } = this.props + + const Selected = betaUI || isMascara || firstTime ? App : OldApp return h(Selected) } diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index b7f2e7277..7c9b6dbc6 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -572,7 +572,7 @@ SendTransactionScreen.prototype.getEditedTx = function () { from: ethUtil.addHexPrefix(from), gas: ethUtil.addHexPrefix(gas), gasPrice: ethUtil.addHexPrefix(gasPrice), - } + }, } if (selectedToken) { diff --git a/ui/index.js b/ui/index.js index fff677471..2aa30d3fe 100644 --- a/ui/index.js +++ b/ui/index.js @@ -8,7 +8,6 @@ global.log = require('loglevel') module.exports = launchMetamaskUi - log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn') function launchMetamaskUi (opts, cb) { -- cgit From a218008adf85dfb5fa8ca93c789e14d9f2090813 Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Fri, 22 Dec 2017 10:43:02 -0800 Subject: Track usage of old and new UI (#2794) [NewUI] Track usage of old and new UI --- ui/app/actions.js | 37 +++++++++++++++++++++++++++++++++---- ui/app/reducers/metamask.js | 7 +++++++ ui/app/select-app.js | 13 ++++++++++--- ui/app/settings.js | 10 +++++++--- ui/index.js | 6 ++++++ 5 files changed, 63 insertions(+), 10 deletions(-) (limited to 'ui') diff --git a/ui/app/actions.js b/ui/app/actions.js index e8271c9a7..bd3aab45a 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -240,12 +240,17 @@ var actions = { SET_USE_BLOCKIE: 'SET_USE_BLOCKIE', setUseBlockie, - + // Feature Flags setFeatureFlag, updateFeatureFlags, UPDATE_FEATURE_FLAGS: 'UPDATE_FEATURE_FLAGS', - + + // Network + setNetworkEndpoints, + updateNetworkEndpointType, + UPDATE_NETWORK_ENDPOINT_TYPE: 'UPDATE_NETWORK_ENDPOINT_TYPE', + retryTransaction, } @@ -1489,7 +1494,7 @@ function reshowQrCode (data, coin) { dispatch(actions.showLoadingIndication()) shapeShiftRequest('marketinfo', {pair: `${coin.toLowerCase()}_eth`}, (mktResponse) => { if (mktResponse.error) return dispatch(actions.displayWarning(mktResponse.error)) - + var message = [ `Deposit your ${coin} to the address bellow:`, `Deposit Limit: ${mktResponse.limit}`, @@ -1565,7 +1570,7 @@ function setFeatureFlag (feature, activated, notificationType) { dispatch(actions.hideLoadingIndication()) if (err) { dispatch(actions.displayWarning(err.message)) - reject(err) + return reject(err) } dispatch(actions.updateFeatureFlags(updatedFeatureFlags)) notificationType && dispatch(actions.showModal({ name: notificationType })) @@ -1646,3 +1651,27 @@ function setUseBlockie (val) { }) } } + +function setNetworkEndpoints (networkEndpointType) { + return dispatch => { + log.debug('background.setNetworkEndpoints') + return new Promise((resolve, reject) => { + background.setNetworkEndpoints(networkEndpointType, err => { + if (err) { + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + + dispatch(actions.updateNetworkEndpointType(networkEndpointType)) + resolve(networkEndpointType) + }) + }) + } +} + +function updateNetworkEndpointType (networkEndpointType) { + return { + type: actions.UPDATE_NETWORK_ENDPOINT_TYPE, + value: networkEndpointType, + } +} diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 95b41e5f3..294c29948 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -1,6 +1,7 @@ const extend = require('xtend') const actions = require('../actions') const MetamascaraPlatform = require('../../../app/scripts/platforms/window') +const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/config').enums module.exports = reduceMetamask @@ -39,6 +40,7 @@ function reduceMetamask (state, action) { coinOptions: {}, useBlockie: false, featureFlags: {}, + networkEndpointType: OLD_UI_NETWORK_TYPE, }, state.metamask) switch (action.type) { @@ -335,6 +337,11 @@ function reduceMetamask (state, action) { featureFlags: action.value, }) + case actions.UPDATE_NETWORK_ENDPOINT_TYPE: + return extend(metamaskState, { + networkEndpointType: action.value, + }) + default: return metamaskState diff --git a/ui/app/select-app.js b/ui/app/select-app.js index 0b837b547..ac6867aeb 100644 --- a/ui/app/select-app.js +++ b/ui/app/select-app.js @@ -5,7 +5,8 @@ const h = require('react-hyperscript') const App = require('./app') const OldApp = require('../../old-ui/app/app') const { autoAddToBetaUI } = require('./selectors') -const { setFeatureFlag } = require('./actions') +const { setFeatureFlag, setNetworkEndpoints } = require('./actions') +const { BETA_UI_NETWORK_TYPE } = require('../../app/scripts/config').enums function mapStateToProps (state) { return { @@ -19,8 +20,14 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - setFeatureFlagWithModal: () => dispatch(setFeatureFlag('betaUI', true, 'BETA_UI_NOTIFICATION_MODAL')), - setFeatureFlagWithoutModal: () => dispatch(setFeatureFlag('betaUI', true)), + setFeatureFlagWithModal: () => { + return dispatch(setFeatureFlag('betaUI', true, 'BETA_UI_NOTIFICATION_MODAL')) + .then(() => dispatch(setNetworkEndpoints(BETA_UI_NETWORK_TYPE))) + }, + setFeatureFlagWithoutModal: () => { + return dispatch(setFeatureFlag('betaUI', true)) + .then(() => dispatch(setNetworkEndpoints(BETA_UI_NETWORK_TYPE))) + }, } } module.exports = connect(mapStateToProps, mapDispatchToProps)(SelectedApp) diff --git a/ui/app/settings.js b/ui/app/settings.js index 74b282a98..a3dd65f14 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -9,6 +9,7 @@ const { exportAsFile } = require('./util') const TabBar = require('./components/tab-bar') const SimpleDropdown = require('./components/dropdowns/simple-dropdown') const ToggleButton = require('react-toggle-button') +const { OLD_UI_NETWORK_TYPE } = require('../../app/scripts/config').enums const getInfuraCurrencyOptions = () => { const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { @@ -228,7 +229,7 @@ class Settings extends Component { ]) ) } - + renderOldUI () { const { setFeatureFlagToBeta } = this.props @@ -265,7 +266,7 @@ class Settings extends Component { ]) ) } - + renderLogo () { return ( h('div.settings__info-logo-wrapper', [ @@ -405,7 +406,10 @@ const mapDispatchToProps = dispatch => { displayWarning: warning => dispatch(actions.displayWarning(warning)), revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()), setUseBlockie: value => dispatch(actions.setUseBlockie(value)), - setFeatureFlagToBeta: () => dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')), + setFeatureFlagToBeta: () => { + return dispatch(actions.setFeatureFlag('betaUI', false, 'OLD_UI_NOTIFICATION_MODAL')) + .then(() => dispatch(actions.setNetworkEndpoints(OLD_UI_NETWORK_TYPE))) + }, } } diff --git a/ui/index.js b/ui/index.js index 2aa30d3fe..bc3676c1f 100644 --- a/ui/index.js +++ b/ui/index.js @@ -4,6 +4,8 @@ const Root = require('./app/root') const actions = require('./app/actions') const configureStore = require('./app/store') const txHelper = require('./lib/tx-helper') +const { OLD_UI_NETWORK_TYPE, BETA_UI_NETWORK_TYPE } = require('../app/scripts/config').enums + global.log = require('loglevel') module.exports = launchMetamaskUi @@ -35,6 +37,10 @@ function startApp (metamaskState, accountManager, opts) { networkVersion: opts.networkVersion, }) + const useBetaUi = metamaskState.featureFlags.betaUI + const networkEndpointType = useBetaUi ? BETA_UI_NETWORK_TYPE : OLD_UI_NETWORK_TYPE + store.dispatch(actions.setNetworkEndpoints(networkEndpointType)) + // if unconfirmed txs, start on txConf page const unapprovedTxsAll = txHelper(metamaskState.unapprovedTxs, metamaskState.unapprovedMsgs, metamaskState.unapprovedPersonalMsgs, metamaskState.unapprovedTypedMessages, metamaskState.network) const numberOfUnapprivedTx = unapprovedTxsAll.length -- cgit