@@ -27,6 +27,7 @@ const ConfirmPageContainerSummary = props => {
className="confirm-page-container-summary__identicon"
diameter={36}
address={identiconAddress}
+ image={assetImage}
/>
)
}
@@ -51,6 +52,7 @@ ConfirmPageContainerSummary.propTypes = {
className: PropTypes.string,
identiconAddress: PropTypes.string,
nonce: PropTypes.string,
+ assetImage: PropTypes.string,
}
export default ConfirmPageContainerSummary
diff --git a/ui/app/components/confirm-page-container/confirm-page-container.component.js b/ui/app/components/confirm-page-container/confirm-page-container.component.js
index 24ff05353..b1582051e 100644
--- a/ui/app/components/confirm-page-container/confirm-page-container.component.js
+++ b/ui/app/components/confirm-page-container/confirm-page-container.component.js
@@ -38,6 +38,7 @@ export default class ConfirmPageContainer extends Component {
detailsComponent: PropTypes.node,
identiconAddress: PropTypes.string,
nonce: PropTypes.string,
+ assetImage: PropTypes.string,
summaryComponent: PropTypes.node,
warning: PropTypes.string,
// Footer
@@ -70,8 +71,10 @@ export default class ConfirmPageContainer extends Component {
onSubmit,
identiconAddress,
nonce,
+ assetImage,
warning,
} = this.props
+ const renderAssetImage = contentComponent || (!contentComponent && !identiconAddress)
return (
@@ -84,6 +87,7 @@ export default class ConfirmPageContainer extends Component {
senderAddress={fromAddress}
recipientName={toName}
recipientAddress={toAddress}
+ assetImage={renderAssetImage ? assetImage : undefined}
/>
{
@@ -101,6 +105,7 @@ export default class ConfirmPageContainer extends Component {
errorKey={errorKey}
identiconAddress={identiconAddress}
nonce={nonce}
+ assetImage={assetImage}
warning={warning}
/>
)
diff --git a/ui/app/components/currency-display/currency-display.component.js b/ui/app/components/currency-display/currency-display.component.js
new file mode 100644
index 000000000..e4eb58a2a
--- /dev/null
+++ b/ui/app/components/currency-display/currency-display.component.js
@@ -0,0 +1,31 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { ETH, GWEI } from '../../constants/common'
+
+export default class CurrencyDisplay extends PureComponent {
+ static propTypes = {
+ className: PropTypes.string,
+ displayValue: PropTypes.string,
+ prefix: PropTypes.string,
+ // Used in container
+ currency: PropTypes.oneOf([ETH]),
+ denomination: PropTypes.oneOf([GWEI]),
+ value: PropTypes.string,
+ numberOfDecimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ hideLabel: PropTypes.bool,
+ }
+
+ render () {
+ const { className, displayValue, prefix } = this.props
+ const text = `${prefix || ''}${displayValue}`
+
+ return (
+
+ { text }
+
+ )
+ }
+}
diff --git a/ui/app/components/currency-display/currency-display.container.js b/ui/app/components/currency-display/currency-display.container.js
new file mode 100644
index 000000000..6644a1099
--- /dev/null
+++ b/ui/app/components/currency-display/currency-display.container.js
@@ -0,0 +1,21 @@
+import { connect } from 'react-redux'
+import CurrencyDisplay from './currency-display.component'
+import { getValueFromWeiHex, formatCurrency } from '../../helpers/confirm-transaction/util'
+
+const mapStateToProps = (state, ownProps) => {
+ const { value, numberOfDecimals = 2, currency, denomination, hideLabel } = ownProps
+ const { metamask: { currentCurrency, conversionRate } } = state
+
+ const toCurrency = currency || currentCurrency
+ const convertedValue = getValueFromWeiHex({
+ value, toCurrency, conversionRate, numberOfDecimals, toDenomination: denomination,
+ })
+ const formattedValue = formatCurrency(convertedValue, toCurrency)
+ const displayValue = hideLabel ? formattedValue : `${formattedValue} ${toCurrency.toUpperCase()}`
+
+ return {
+ displayValue,
+ }
+}
+
+export default connect(mapStateToProps)(CurrencyDisplay)
diff --git a/ui/app/components/currency-display/index.js b/ui/app/components/currency-display/index.js
new file mode 100644
index 000000000..38f08765f
--- /dev/null
+++ b/ui/app/components/currency-display/index.js
@@ -0,0 +1 @@
+export { default } from './currency-display.container'
diff --git a/ui/app/components/currency-display/tests/currency-display.component.test.js b/ui/app/components/currency-display/tests/currency-display.component.test.js
new file mode 100644
index 000000000..d9ef052f1
--- /dev/null
+++ b/ui/app/components/currency-display/tests/currency-display.component.test.js
@@ -0,0 +1,27 @@
+import React from 'react'
+import assert from 'assert'
+import { shallow } from 'enzyme'
+import CurrencyDisplay from '../currency-display.component'
+
+describe('CurrencyDisplay Component', () => {
+ it('should render text with a className', () => {
+ const wrapper = shallow(
)
+
+ assert.ok(wrapper.hasClass('currency-display'))
+ assert.equal(wrapper.text(), '$123.45')
+ })
+
+ it('should render text with a prefix', () => {
+ const wrapper = shallow(
)
+
+ assert.ok(wrapper.hasClass('currency-display'))
+ assert.equal(wrapper.text(), '-$123.45')
+ })
+})
diff --git a/ui/app/components/currency-display/tests/currency-display.container.test.js b/ui/app/components/currency-display/tests/currency-display.container.test.js
new file mode 100644
index 000000000..5265bbb04
--- /dev/null
+++ b/ui/app/components/currency-display/tests/currency-display.container.test.js
@@ -0,0 +1,105 @@
+import assert from 'assert'
+import proxyquire from 'proxyquire'
+
+let mapStateToProps
+
+proxyquire('../currency-display.container.js', {
+ 'react-redux': {
+ connect: ms => {
+ mapStateToProps = ms
+ return () => ({})
+ },
+ },
+})
+
+describe('CurrencyDisplay container', () => {
+ describe('mapStateToProps()', () => {
+ it('should return the correct props', () => {
+ const mockState = {
+ metamask: {
+ conversionRate: 280.45,
+ currentCurrency: 'usd',
+ },
+ }
+
+ const tests = [
+ {
+ props: {
+ value: '0x2386f26fc10000',
+ numberOfDecimals: 2,
+ currency: 'usd',
+ },
+ result: {
+ displayValue: '$2.80 USD',
+ },
+ },
+ {
+ props: {
+ value: '0x2386f26fc10000',
+ },
+ result: {
+ displayValue: '$2.80 USD',
+ },
+ },
+ {
+ props: {
+ value: '0x1193461d01595930',
+ currency: 'ETH',
+ numberOfDecimals: 3,
+ },
+ result: {
+ displayValue: '1.266 ETH',
+ },
+ },
+ {
+ props: {
+ value: '0x1193461d01595930',
+ currency: 'ETH',
+ numberOfDecimals: 3,
+ hideLabel: true,
+ },
+ result: {
+ displayValue: '1.266',
+ },
+ },
+ {
+ props: {
+ value: '0x3b9aca00',
+ currency: 'ETH',
+ denomination: 'GWEI',
+ hideLabel: true,
+ },
+ result: {
+ displayValue: '1',
+ },
+ },
+ {
+ props: {
+ value: '0x3b9aca00',
+ currency: 'ETH',
+ denomination: 'WEI',
+ hideLabel: true,
+ },
+ result: {
+ displayValue: '1000000000',
+ },
+ },
+ {
+ props: {
+ value: '0x3b9aca00',
+ currency: 'ETH',
+ numberOfDecimals: 100,
+ hideLabel: true,
+ },
+ result: {
+ displayValue: '1e-9',
+ },
+ },
+ ]
+
+ tests.forEach(({ props, result }) => {
+ assert.deepEqual(mapStateToProps(mockState, props), result)
+ })
+ })
+ })
+})
diff --git a/ui/app/components/custom-radio-list.js b/ui/app/components/custom-radio-list.js
deleted file mode 100644
index a4c525396..000000000
--- a/ui/app/components/custom-radio-list.js
+++ /dev/null
@@ -1,60 +0,0 @@
-const Component = require('react').Component
-const h = require('react-hyperscript')
-const inherits = require('util').inherits
-
-module.exports = RadioList
-
-inherits(RadioList, Component)
-function RadioList () {
- Component.call(this)
-}
-
-RadioList.prototype.render = function () {
- const props = this.props
- const activeClass = '.custom-radio-selected'
- const inactiveClass = '.custom-radio-inactive'
- const {
- labels,
- defaultFocus,
- } = props
-
-
- return (
- h('.flex-row', {
- style: {
- fontSize: '12px',
- },
- }, [
- h('.flex-column.custom-radios', {
- style: {
- marginRight: '5px',
- },
- },
- labels.map((lable, i) => {
- let isSelcted = (this.state !== null)
- isSelcted = isSelcted ? (this.state.selected === lable) : (defaultFocus === lable)
- return h(isSelcted ? activeClass : inactiveClass, {
- title: lable,
- onClick: (event) => {
- this.setState({selected: event.target.title})
- props.onClick(event)
- },
- })
- })
- ),
- h('.text', {},
- labels.map((lable) => {
- if (props.subtext) {
- return h('.flex-row', {}, [
- h('.radio-titles', lable),
- h('.radio-titles-subtext', `- ${props.subtext[lable]}`),
- ])
- } else {
- return h('.radio-titles', lable)
- }
- })
- ),
- ])
- )
-}
-
diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js
index c255fd64d..e67fbe45b 100644
--- a/ui/app/components/customize-gas-modal/index.js
+++ b/ui/app/components/customize-gas-modal/index.js
@@ -5,6 +5,7 @@ const inherits = require('util').inherits
const connect = require('react-redux').connect
const actions = require('../../actions')
const GasModalCard = require('./gas-modal-card')
+import Button from '../button'
const ethUtil = require('ethereumjs-util')
@@ -353,16 +354,16 @@ CustomizeGasModal.prototype.render = function () {
}, [this.context.t('revert')]),
h('div.send-v2__customize-gas__buttons', [
- h('button.btn-default.send-v2__customize-gas__cancel', {
+ h(Button, {
+ type: 'default',
+ className: 'send-v2__customize-gas__cancel',
onClick: this.props.hideModal,
- style: {
- marginRight: '10px',
- },
}, [this.context.t('cancel')]),
-
- h('button.btn-primary.send-v2__customize-gas__save', {
+ h(Button, {
+ type: 'primary',
+ className: 'send-v2__customize-gas__save',
onClick: () => !error && this.save(newGasPrice, gasLimit, gasTotal),
- className: error && 'btn-primary--disabled',
+ disabled: error,
}, [this.context.t('save')]),
]),
diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js
index 179b6617f..b497f5c09 100644
--- a/ui/app/components/dropdowns/components/account-dropdowns.js
+++ b/ui/app/components/dropdowns/components/account-dropdowns.js
@@ -459,7 +459,7 @@ const mapDispatchToProps = (dispatch) => {
function mapStateToProps (state) {
return {
keyrings: state.metamask.keyrings,
- sidebarOpen: state.appState.sidebarOpen,
+ sidebarOpen: state.appState.sidebar.isOpen,
}
}
diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js
index e5363ff56..63a30dd82 100644
--- a/ui/app/components/dropdowns/network-dropdown.js
+++ b/ui/app/components/dropdowns/network-dropdown.js
@@ -272,10 +272,12 @@ NetworkDropdown.prototype.getNetworkName = function () {
NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) {
const props = this.props
- const rpcTarget = provider.rpcTarget
+ const reversedRpcList = rpcList.slice().reverse()
- return rpcList.map((rpc) => {
- if ((rpc === 'http://localhost:8545') || (rpc === rpcTarget)) {
+ return reversedRpcList.map((rpc) => {
+ const currentRpcTarget = provider.type === 'rpc' && rpc === provider.rpcTarget
+
+ if ((rpc === 'http://localhost:8545') || currentRpcTarget) {
return null
} else {
return h(
@@ -291,11 +293,11 @@ NetworkDropdown.prototype.renderCommonRpc = function (rpcList, provider) {
},
},
[
- rpcTarget === rpc ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
+ currentRpcTarget ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'),
h('i.fa.fa-question-circle.fa-med.menu-icon-circle'),
h('span.network-name-item', {
style: {
- color: rpcTarget === rpc ? '#ffffff' : '#9b9b9b',
+ color: currentRpcTarget ? '#ffffff' : '#9b9b9b',
},
}, rpc),
]
diff --git a/ui/app/components/hex-as-decimal-input.js b/ui/app/components/hex-as-decimal-input.js
deleted file mode 100644
index 75303a34a..000000000
--- a/ui/app/components/hex-as-decimal-input.js
+++ /dev/null
@@ -1,161 +0,0 @@
-const Component = require('react').Component
-const PropTypes = require('prop-types')
-const h = require('react-hyperscript')
-const inherits = require('util').inherits
-const ethUtil = require('ethereumjs-util')
-const BN = ethUtil.BN
-const extend = require('xtend')
-const connect = require('react-redux').connect
-
-HexAsDecimalInput.contextTypes = {
- t: PropTypes.func,
-}
-
-module.exports = connect()(HexAsDecimalInput)
-
-
-inherits(HexAsDecimalInput, Component)
-function HexAsDecimalInput () {
- this.state = { invalid: null }
- Component.call(this)
-}
-
-/* Hex as Decimal Input
- *
- * A component for allowing easy, decimal editing
- * of a passed in hex string value.
- *
- * On change, calls back its `onChange` function parameter
- * and passes it an updated hex string.
- */
-
-HexAsDecimalInput.prototype.render = function () {
- const props = this.props
- const state = this.state
-
- const { value, onChange, min, max } = props
-
- const toEth = props.toEth
- const suffix = props.suffix
- const decimalValue = decimalize(value, toEth)
- const style = props.style
-
- return (
- h('.flex-column', [
- h('.flex-row', {
- style: {
- alignItems: 'flex-end',
- lineHeight: '13px',
- fontFamily: 'Montserrat Light',
- textRendering: 'geometricPrecision',
- },
- }, [
- h('input.hex-input', {
- type: 'number',
- required: true,
- min: min,
- max: max,
- style: extend({
- display: 'block',
- textAlign: 'right',
- backgroundColor: 'transparent',
- border: '1px solid #bdbdbd',
-
- }, style),
- value: parseInt(decimalValue),
- onBlur: (event) => {
- this.updateValidity(event)
- },
- onChange: (event) => {
- this.updateValidity(event)
- const hexString = (event.target.value === '') ? '' : hexify(event.target.value)
- onChange(hexString)
- },
- onInvalid: (event) => {
- const msg = this.constructWarning()
- if (msg === state.invalid) {
- return
- }
- this.setState({ invalid: msg })
- event.preventDefault()
- return false
- },
- }),
- h('div', {
- style: {
- color: ' #AEAEAE',
- fontSize: '12px',
- marginLeft: '5px',
- marginRight: '6px',
- width: '20px',
- },
- }, suffix),
- ]),
-
- state.invalid ? h('span.error', {
- style: {
- position: 'absolute',
- right: '0px',
- textAlign: 'right',
- transform: 'translateY(26px)',
- padding: '3px',
- background: 'rgba(255,255,255,0.85)',
- zIndex: '1',
- textTransform: 'capitalize',
- border: '2px solid #E20202',
- },
- }, state.invalid) : null,
- ])
- )
-}
-
-HexAsDecimalInput.prototype.setValid = function (message) {
- this.setState({ invalid: null })
-}
-
-HexAsDecimalInput.prototype.updateValidity = function (event) {
- const target = event.target
- const value = this.props.value
- const newValue = target.value
-
- if (value === newValue) {
- return
- }
-
- const valid = target.checkValidity()
- if (valid) {
- this.setState({ invalid: null })
- }
-}
-
-HexAsDecimalInput.prototype.constructWarning = function () {
- const { name, min, max } = this.props
- let message = name ? name + ' ' : ''
-
- if (min && max) {
- message += this.context.t('betweenMinAndMax', [min, max])
- } else if (min) {
- message += this.context.t('greaterThanMin', [min])
- } else if (max) {
- message += this.context.t('lessThanMax', [max])
- } else {
- message += this.context.t('invalidInput')
- }
-
- return message
-}
-
-function hexify (decimalString) {
- const hexBN = new BN(parseInt(decimalString), 10)
- return '0x' + hexBN.toString('hex')
-}
-
-function decimalize (input, toEth) {
- if (input === '') {
- return ''
- } else {
- const strippedInput = ethUtil.stripHexPrefix(input)
- const inputBN = new BN(strippedInput, 'hex')
- return inputBN.toString(10)
- }
-}
diff --git a/ui/app/components/hex-to-decimal/hex-to-decimal.component.js b/ui/app/components/hex-to-decimal/hex-to-decimal.component.js
new file mode 100644
index 000000000..6847a6919
--- /dev/null
+++ b/ui/app/components/hex-to-decimal/hex-to-decimal.component.js
@@ -0,0 +1,21 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import { hexToDecimal } from '../../helpers/conversions.util'
+
+export default class HexToDecimal extends PureComponent {
+ static propTypes = {
+ className: PropTypes.string,
+ value: PropTypes.string,
+ }
+
+ render () {
+ const { className, value } = this.props
+ const decimalValue = hexToDecimal(value)
+
+ return (
+
+ { decimalValue }
+
+ )
+ }
+}
diff --git a/ui/app/components/hex-to-decimal/index.js b/ui/app/components/hex-to-decimal/index.js
new file mode 100644
index 000000000..6e8567ca9
--- /dev/null
+++ b/ui/app/components/hex-to-decimal/index.js
@@ -0,0 +1 @@
+export { default } from './hex-to-decimal.component'
diff --git a/ui/app/components/hex-to-decimal/tests/hex-to-decimal.component.test.js b/ui/app/components/hex-to-decimal/tests/hex-to-decimal.component.test.js
new file mode 100644
index 000000000..c98da9ad4
--- /dev/null
+++ b/ui/app/components/hex-to-decimal/tests/hex-to-decimal.component.test.js
@@ -0,0 +1,26 @@
+import React from 'react'
+import assert from 'assert'
+import { shallow } from 'enzyme'
+import HexToDecimal from '../hex-to-decimal.component'
+
+describe('HexToDecimal Component', () => {
+ it('should render a prefixed hex as a decimal with a className', () => {
+ const wrapper = shallow(
)
+
+ assert.ok(wrapper.hasClass('hex-to-decimal'))
+ assert.equal(wrapper.text(), '12345')
+ })
+
+ it('should render an unprefixed hex as a decimal with a className', () => {
+ const wrapper = shallow(
)
+
+ assert.ok(wrapper.hasClass('hex-to-decimal'))
+ assert.equal(wrapper.text(), '6789')
+ })
+})
diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js
index 424048745..7bd921892 100644
--- a/ui/app/components/identicon.js
+++ b/ui/app/components/identicon.js
@@ -26,36 +26,43 @@ function mapStateToProps (state) {
IdenticonComponent.prototype.render = function () {
var props = this.props
- const { className = '', address } = props
+ const { className = '', address, image } = props
var diameter = props.diameter || this.defaultDiameter
-
- return address
- ? (
- h('div', {
- className: `${className} identicon`,
- key: 'identicon-' + address,
- style: {
- display: 'flex',
- flexShrink: 0,
- alignItems: 'center',
- justifyContent: 'center',
- height: diameter,
- width: diameter,
- borderRadius: diameter / 2,
- overflow: 'hidden',
- },
- })
- )
- : (
- h('img.balance-icon', {
- src: './images/eth_logo.svg',
- style: {
- height: diameter,
- width: diameter,
- borderRadius: diameter / 2,
- },
- })
- )
+ const style = {
+ height: diameter,
+ width: diameter,
+ borderRadius: diameter / 2,
+ }
+ if (image) {
+ return h('img', {
+ className: `${className} identicon`,
+ src: image,
+ style: {
+ ...style,
+ },
+ })
+ } else if (address) {
+ return h('div', {
+ className: `${className} identicon`,
+ key: 'identicon-' + address,
+ style: {
+ display: 'flex',
+ flexShrink: 0,
+ alignItems: 'center',
+ justifyContent: 'center',
+ ...style,
+ overflow: 'hidden',
+ },
+ })
+ } else {
+ return h('img.balance-icon', {
+ className,
+ src: './images/eth_logo.svg',
+ style: {
+ ...style,
+ },
+ })
+ }
}
IdenticonComponent.prototype.componentDidMount = function () {
diff --git a/ui/app/components/index.scss b/ui/app/components/index.scss
index b3e14ce23..983d6b98a 100644
--- a/ui/app/components/index.scss
+++ b/ui/app/components/index.scss
@@ -1,21 +1,47 @@
+@import './app-header/index';
+
@import './button-group/index';
+@import './card/index';
+
+@import './confirm-page-container/index';
+
@import './export-text-container/index';
-@import './selected-account/index';
-
@import './info-box/index';
-@import './network-display/index';
+@import './menu-bar/index';
-@import './confirm-page-container/index';
+@import './modals/index';
+
+@import './network-display/index';
@import './page-container/index';
@import './pages/index';
-@import './modals/index';
+@import './selected-account/index';
@import './sender-to-recipient/index';
@import './tabs/index';
+
+@import './transaction-activity-log/index';
+
+@import './transaction-breakdown/index';
+
+@import './transaction-view/index';
+
+@import './transaction-view-balance/index';
+
+@import './transaction-list/index';
+
+@import './transaction-list-item/index';
+
+@import './transaction-list-item-details/index';
+
+@import './transaction-status/index';
+
+@import './app-header/index';
+
+@import './sidebars/index';
diff --git a/ui/app/components/input-number.js b/ui/app/components/input-number.js
index 59c6842ef..eec5e3740 100644
--- a/ui/app/components/input-number.js
+++ b/ui/app/components/input-number.js
@@ -66,13 +66,16 @@ InputNumber.prototype.render = function () {
}),
h('span.gas-tooltip-input-detail', {}, [unitLabel]),
h('div.gas-tooltip-input-arrows', {}, [
- h('i.fa.fa-angle-up', {
+ h('div.gas-tooltip-input-arrow-wrapper', {
onClick: () => this.setValue(addCurrencies(value, step, { toNumericBase: 'dec' })),
- }),
- h('i.fa.fa-angle-down', {
- style: { cursor: 'pointer' },
+ }, [
+ h('i.fa.fa-angle-up'),
+ ]),
+ h('div.gas-tooltip-input-arrow-wrapper', {
onClick: () => this.setValue(subtractCurrencies(value, step, { toNumericBase: 'dec' })),
- }),
+ }, [
+ h('i.fa.fa-angle-down'),
+ ]),
]),
])
}
diff --git a/ui/app/components/menu-bar/index.js b/ui/app/components/menu-bar/index.js
new file mode 100644
index 000000000..c5760847f
--- /dev/null
+++ b/ui/app/components/menu-bar/index.js
@@ -0,0 +1 @@
+export { default } from './menu-bar.container'
diff --git a/ui/app/components/menu-bar/index.scss b/ui/app/components/menu-bar/index.scss
new file mode 100644
index 000000000..f699f4090
--- /dev/null
+++ b/ui/app/components/menu-bar/index.scss
@@ -0,0 +1,23 @@
+.menu-bar {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ flex: 0 0 auto;
+ margin-bottom: 16px;
+ padding: 5px;
+ border-bottom: 1px solid #e5e5e5;
+
+ &__sidebar-button {
+ font-size: 1.25rem;
+ cursor: pointer;
+ padding: 10px;
+ }
+
+ &__open-in-browser {
+ cursor: pointer;
+ display: flex;
+ justify-content: center;
+ padding: 10px;
+ }
+}
diff --git a/ui/app/components/menu-bar/menu-bar.component.js b/ui/app/components/menu-bar/menu-bar.component.js
new file mode 100644
index 000000000..eee9feebb
--- /dev/null
+++ b/ui/app/components/menu-bar/menu-bar.component.js
@@ -0,0 +1,52 @@
+import React, { PureComponent } from 'react'
+import PropTypes from 'prop-types'
+import Tooltip from '../tooltip'
+import SelectedAccount from '../selected-account'
+
+export default class MenuBar extends PureComponent {
+ static contextTypes = {
+ t: PropTypes.func,
+ }
+
+ static propTypes = {
+ hideSidebar: PropTypes.func,
+ isMascara: PropTypes.bool,
+ sidebarOpen: PropTypes.bool,
+ showSidebar: PropTypes.func,
+ }
+
+ render () {
+ const { t } = this.context
+ const { isMascara, sidebarOpen, hideSidebar, showSidebar } = this.props
+
+ return (
+
+
+ sidebarOpen ? hideSidebar() : showSidebar()}
+ />
+
+
+ {
+ !isMascara && (
+
+ global.platform.openExtensionInBrowser()}
+ >
+
![](images/popout.svg)
+
+
+ )
+ }
+
+ )
+ }
+}
diff --git a/ui/app/components/menu-bar/menu-bar.container.js b/ui/app/components/menu-bar/menu-bar.container.js
new file mode 100644
index 000000000..ae32882ae
--- /dev/null
+++ b/ui/app/components/menu-bar/menu-bar.container.js
@@ -0,0 +1,26 @@
+import { connect } from 'react-redux'
+import MenuBar from './menu-bar.component'
+import { showSidebar, hideSidebar } from '../../actions'
+
+const mapStateToProps = state => {
+ const { appState: { sidebar: { isOpen }, isMascara } } = state
+
+ return {
+ sidebarOpen: isOpen,
+ isMascara,
+ }
+}
+
+const mapDispatchToProps = dispatch => {
+ return {
+ showSidebar: () => {
+ dispatch(showSidebar({
+ transitionName: 'sidebar-right',
+ type: 'wallet-view',
+ }))
+ },
+ hideSidebar: () => dispatch(hideSidebar()),
+ }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(MenuBar)
diff --git a/ui/app/components/modals/account-details-modal.js b/ui/app/components/modals/account-details-modal.js
index 5607cf051..248ffe008 100644
--- a/ui/app/components/modals/account-details-modal.js
+++ b/ui/app/components/modals/account-details-modal.js
@@ -10,10 +10,13 @@ const genAccountLink = require('../../../lib/account-link.js')
const QrView = require('../qr-code')
const EditableLabel = require('../editable-label')
+import Button from '../button'
+
function mapStateToProps (state) {
return {
network: state.metamask.network,
selectedIdentity: getSelectedIdentity(state),
+ keyrings: state.metamask.keyrings,
}
}
@@ -50,9 +53,20 @@ AccountDetailsModal.prototype.render = function () {
network,
showExportPrivateKeyModal,
setAccountLabel,
+ keyrings,
} = this.props
const { name, address } = selectedIdentity
+ const keyring = keyrings.find((kr) => {
+ return kr.accounts.includes(address)
+ })
+
+ let exportPrivateKeyFeatureEnabled = true
+ // This feature is disabled for hardware wallets
+ if (keyring && keyring.type.search('Hardware') !== -1) {
+ exportPrivateKeyFeatureEnabled = false
+ }
+
return h(AccountModalContainer, {}, [
h(EditableLabel, {
className: 'account-modal__name',
@@ -68,14 +82,19 @@ AccountDetailsModal.prototype.render = function () {
h('div.account-modal-divider'),
- h('button.btn-primary.account-modal__button', {
+ h(Button, {
+ type: 'primary',
+ className: 'account-modal__button',
onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }),
}, this.context.t('etherscanView')),
// Holding on redesign for Export Private Key functionality
- h('button.btn-primary.account-modal__button', {
+
+ exportPrivateKeyFeatureEnabled ? h(Button, {
+ type: 'primary',
+ className: 'account-modal__button',
onClick: () => showExportPrivateKeyModal(),
- }, this.context.t('exportPrivateKey')),
+ }, this.context.t('exportPrivateKey')) : null,
])
}
diff --git a/ui/app/components/modals/account-modal-container.js b/ui/app/components/modals/account-modal-container.js
index a9856b20f..aa0593df8 100644
--- a/ui/app/components/modals/account-modal-container.js
+++ b/ui/app/components/modals/account-modal-container.js
@@ -7,9 +7,9 @@ const actions = require('../../actions')
const { getSelectedIdentity } = require('../../selectors')
const Identicon = require('../identicon')
-function mapStateToProps (state) {
+function mapStateToProps (state, ownProps) {
return {
- selectedIdentity: getSelectedIdentity(state),
+ selectedIdentity: ownProps.selectedIdentity || getSelectedIdentity(state),
}
}
diff --git a/ui/app/components/modals/customize-gas/customize-gas.component.js b/ui/app/components/modals/customize-gas/customize-gas.component.js
index 0337c5413..3f526bd43 100644
--- a/ui/app/components/modals/customize-gas/customize-gas.component.js
+++ b/ui/app/components/modals/customize-gas/customize-gas.component.js
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types'
import GasModalCard from '../../customize-gas-modal/gas-modal-card'
import { MIN_GAS_PRICE_GWEI } from '../../send/send.constants'
+import Button from '../../button'
import {
getDecimalGasLimit,
@@ -116,21 +117,23 @@ export default class CustomizeGas extends Component {
{ t('revert') }
-
-