diff --git a/CHANGELOG.md b/CHANGELOG.md index 868983c15..b45e18641 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Current Master +## 4.7.1 Fri Jun 01 2018 + +- Fix bug where errors were not returned to Dapps. + ## 4.7.0 Wed May 30 2018 - Fix Brave support diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 4851508a3..40d362f51 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -523,6 +523,9 @@ "networks": { "message": "Networks" }, + "nevermind": { + "message": "Nevermind" + }, "newAccount": { "message": "New Account" }, @@ -637,9 +640,15 @@ "rejected": { "message": "Rejected" }, + "reset": { + "message": "Reset" + }, "resetAccount": { "message": "Reset Account" }, + "resetAccountDescription": { + "message": "Resetting your account will clear your transaction history." + }, "restoreFromSeed": { "message": "Restore account?" }, @@ -897,7 +906,7 @@ "message": "Welcome to the New UI (Beta)" }, "uiWelcomeMessage": { - "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." + "message": "You are now using the new Metamask UI." }, "unapproved": { "message": "Unapproved" diff --git a/app/manifest.json b/app/manifest.json index 52ce8cc0a..dbce13f7c 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "4.7.0", + "version": "4.7.1", "manifest_version": 2, "author": "https://metamask.io", "description": "__MSG_appDescription__", diff --git a/app/scripts/controllers/user-actions.js b/app/scripts/controllers/user-actions.js new file mode 100644 index 000000000..f777054b8 --- /dev/null +++ b/app/scripts/controllers/user-actions.js @@ -0,0 +1,17 @@ +const MessageManager = require('./lib/message-manager') +const PersonalMessageManager = require('./lib/personal-message-manager') +const TypedMessageManager = require('./lib/typed-message-manager') + +class UserActionController { + + constructor (opts = {}) { + + this.messageManager = new MessageManager() + this.personalMessageManager = new PersonalMessageManager() + this.typedMessageManager = new TypedMessageManager() + + } + +} + +module.exports = UserActionController diff --git a/app/scripts/lib/createErrorMiddleware.js b/app/scripts/lib/createErrorMiddleware.js index baed99e45..c70beddfd 100644 --- a/app/scripts/lib/createErrorMiddleware.js +++ b/app/scripts/lib/createErrorMiddleware.js @@ -59,6 +59,7 @@ function createErrorMiddleware ({ override = true } = {}) { if (!error) { return done() } sanitizeRPCError(error) log.error(`MetaMask - RPC Error: ${error.message}`, error) + done() }) } } diff --git a/package-lock.json b/package-lock.json index 4b27c769e..945c47ae0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -309,7 +309,7 @@ }, "@sinonjs/formatio": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", "dev": true, "requires": { @@ -1500,8 +1500,7 @@ }, "dependencies": { "bignumber.js": { - "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2", - "from": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + "version": "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" }, "chai": { "version": "3.5.0", @@ -8014,7 +8013,6 @@ "dependencies": { "async-eventemitter": { "version": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", - "from": "async-eventemitter@github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", "requires": { "async": "2.6.0" } @@ -8174,16 +8172,16 @@ "integrity": "sha512-NNlVB/TBc8p9CblwECjPlUR+7MNQKiBa7tEFxIzZ9MjjNCEYPWDXTm0vJZzuDtVmFxYwIA53UD0QEn0QNxWNEQ==", "dev": true, "requires": { - "bip39": "^2.4.0", - "bluebird": "^3.5.0", - "browser-passworder": "^2.0.3", - "eth-hd-keyring": "^1.2.2", - "eth-sig-util": "^1.4.0", - "eth-simple-keyring": "^1.2.2", - "ethereumjs-util": "^5.1.2", - "loglevel": "^1.5.0", - "obs-store": "^2.4.1", - "promise-filter": "^1.1.0" + "bip39": "2.4.0", + "bluebird": "3.5.1", + "browser-passworder": "2.0.3", + "eth-hd-keyring": "1.2.2", + "eth-sig-util": "1.4.2", + "eth-simple-keyring": "1.2.2", + "ethereumjs-util": "5.2.0", + "loglevel": "1.6.0", + "obs-store": "2.4.1", + "promise-filter": "1.1.0" }, "dependencies": { "babelify": { @@ -8268,7 +8266,6 @@ "dependencies": { "ethereumjs-abi": { "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", - "from": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "requires": { "bn.js": "4.11.8", "ethereumjs-util": "5.1.3" @@ -8296,11 +8293,11 @@ "integrity": "sha512-uQVBYshHUOaXVoat1BpLA/QNMCr4hgdFBgwIB7rRmQ+m3vQQAseUsOM+biPDYzq6end+6LjcccElLpQaIZe6dg==", "dev": true, "requires": { - "eth-sig-util": "^1.4.2", - "ethereumjs-util": "^5.1.1", - "ethereumjs-wallet": "^0.6.0", - "events": "^1.1.1", - "xtend": "^4.0.1" + "eth-sig-util": "1.4.2", + "ethereumjs-util": "5.2.0", + "ethereumjs-wallet": "0.6.0", + "events": "1.1.1", + "xtend": "4.0.1" }, "dependencies": { "ethereumjs-util": { @@ -8502,7 +8499,7 @@ "eth-query": "2.1.2", "ethereumjs-block": "1.7.0", "ethereumjs-tx": "1.3.3", - "ethereumjs-util": "^5.0.1", + "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", "ethereumjs-vm": "2.3.5", "through2": "2.0.3", "treeify": "1.1.0", @@ -8651,7 +8648,7 @@ "async": "2.6.0", "ethereum-common": "0.2.0", "ethereumjs-tx": "1.3.3", - "ethereumjs-util": "^5.0.0", + "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", "merkle-patricia-tree": "2.3.0" } }, @@ -8661,7 +8658,7 @@ "integrity": "sha1-7OBR0+/b53GtKlGNYWMsoqt17Ls=", "requires": { "ethereum-common": "0.0.18", - "ethereumjs-util": "^5.0.0" + "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9" }, "dependencies": { "ethereum-common": { @@ -8673,7 +8670,6 @@ }, "ethereumjs-util": { "version": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", - "from": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", "requires": { "bn.js": "4.11.8", "create-hash": "1.1.3", @@ -9111,7 +9107,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -11827,7 +11823,6 @@ }, "gulp": { "version": "github:gulpjs/gulp#71c094a51c7972d26f557899ddecab0210ef3776", - "from": "github:gulpjs/gulp#4.0", "requires": { "glob-watcher": "4.0.0", "gulp-cli": "2.0.1", @@ -18210,7 +18205,7 @@ "integrity": "sha512-LKd2OoIT9Re/OG38zXbd5pyHIk2IfcOUczCwkYXl5iJIbufg9nqpweh66VfPwMkUlrEvc7YVvtQdmSrB9V9TkQ==", "requires": { "async": "1.5.2", - "ethereumjs-util": "^5.0.0", + "ethereumjs-util": "github:ethereumjs/ethereumjs-util#ac5d0908536b447083ea422b435da27f26615de9", "level-ws": "0.0.0", "levelup": "1.3.9", "memdown": "1.4.1", @@ -31232,8 +31227,7 @@ }, "dependencies": { "bignumber.js": { - "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934", - "from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git" + "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" } } }, @@ -31714,7 +31708,6 @@ }, "websocket": { "version": "git://github.com/frozeman/WebSocket-Node.git#7004c39c42ac98875ab61126e5b4a925430f592c", - "from": "websocket@git://github.com/frozeman/WebSocket-Node.git#7004c39c42ac98875ab61126e5b4a925430f592c", "requires": { "debug": "2.6.9", "nan": "2.8.0", diff --git a/test/integration/lib/add-token.js b/test/integration/lib/add-token.js index e51c854d2..5a08c90cd 100644 --- a/test/integration/lib/add-token.js +++ b/test/integration/lib/add-token.js @@ -43,7 +43,7 @@ async function runAddTokenFlowTest (assert, done) { assert.equal(addTokenTitle[0].textContent, 'Add Tokens', 'add token title is correct') // Cancel Add Token - const cancelAddTokenButton = await queryAsync($, 'button.btn-secondary--lg.page-container__footer-button') + const cancelAddTokenButton = await queryAsync($, 'button.btn-default.btn--large.page-container__footer-button') assert.ok(cancelAddTokenButton[0], 'cancel add token button present') cancelAddTokenButton.click() @@ -75,15 +75,15 @@ async function runAddTokenFlowTest (assert, done) { tokenWrapper[0].click() // Click Next button - let nextButton = await queryAsync($, 'button.btn-primary--lg') + let nextButton = await queryAsync($, 'button.btn-primary.btn--large') assert.equal(nextButton[0].textContent, 'Next', 'next button rendered') nextButton[0].click() // Confirm Add token const confirmAddToken = await queryAsync($, '.confirm-add-token') assert.ok(confirmAddToken[0], 'confirm add token rendered') - assert.ok($('button.btn-primary--lg')[0], 'confirm add token button found') - $('button.btn-primary--lg')[0].click() + assert.ok($('button.btn-primary.btn--large')[0], 'confirm add token button found') + $('button.btn-primary.btn--large')[0].click() // Verify added token image let heroBalance = await queryAsync($, '.hero-balance') @@ -120,7 +120,7 @@ async function runAddTokenFlowTest (assert, done) { const errorMessage = await queryAsync($, '#custom-symbol-helper-text') assert.ok(errorMessage[0], 'error rendered') - $('button.btn-secondary--lg')[0].click() + $('button.btn-default.btn--large')[0].click() // await timeout(100000) diff --git a/test/integration/lib/confirm-sig-requests.js b/test/integration/lib/confirm-sig-requests.js index 3936ac5fa..d5ed7c77c 100644 --- a/test/integration/lib/confirm-sig-requests.js +++ b/test/integration/lib/confirm-sig-requests.js @@ -38,7 +38,7 @@ async function runConfirmSigRequestsTest(assert, done) { let confirmSigRowValue = await queryAsync($, '.request-signature__row-value') assert.equal(confirmSigRowValue[0].textContent, '0x879a053d4800c6354e76c7985a865d2922c82fb5b3f4577b2fe08b998954f2e0') - let confirmSigSignButton = await queryAsync($, 'button.btn-primary--lg') + let confirmSigSignButton = await queryAsync($, 'button.btn-primary.btn--large') confirmSigSignButton[0].click() confirmSigHeadline = await queryAsync($, '.request-signature__headline') @@ -47,7 +47,7 @@ async function runConfirmSigRequestsTest(assert, done) { confirmSigRowValue = await queryAsync($, '.request-signature__row-value') assert.ok(confirmSigRowValue[0].textContent.match(/^\#\sTerms\sof\sUse/)) - confirmSigSignButton = await queryAsync($, 'button.btn-primary--lg') + confirmSigSignButton = await queryAsync($, 'button.btn-primary.btn--large') confirmSigSignButton[0].click() confirmSigHeadline = await queryAsync($, '.request-signature__headline') @@ -57,7 +57,7 @@ async function runConfirmSigRequestsTest(assert, done) { assert.equal(confirmSigRowValue[0].textContent, 'Hi, Alice!') assert.equal(confirmSigRowValue[1].textContent, '1337') - confirmSigSignButton = await queryAsync($, 'button.btn-primary--lg') + confirmSigSignButton = await queryAsync($, 'button.btn-primary.btn--large') confirmSigSignButton[0].click() const txView = await queryAsync($, '.tx-view') diff --git a/test/integration/lib/send-new-ui.js b/test/integration/lib/send-new-ui.js index 3da3f4f95..176907926 100644 --- a/test/integration/lib/send-new-ui.js +++ b/test/integration/lib/send-new-ui.js @@ -129,7 +129,7 @@ async function runSendFlowTest(assert, done) { await customizeGas(assert, 0, 21000, '0', '$0.00 USD') await customizeGas(assert, 500, 60000, '0.003', '$3.60 USD') - const sendButton = await queryAsync($, 'button.btn-primary--lg.page-container__footer-button') + const sendButton = await queryAsync($, 'button.btn-primary.btn--large.page-container__footer-button') assert.equal(sendButton[0].textContent, 'Next', 'next button rendered') sendButton[0].click() await timeout() @@ -169,13 +169,13 @@ async function runSendFlowTest(assert, done) { sendAmountFieldInputInEdit.val('1.0') reactTriggerChange(sendAmountFieldInputInEdit[0]) - const sendButtonInEdit = await queryAsync($, '.btn-primary--lg.page-container__footer-button') + const sendButtonInEdit = await queryAsync($, '.btn-primary.btn--large.page-container__footer-button') assert.equal(sendButtonInEdit[0].textContent, 'Next', 'next button in edit rendered') selectState.val('send new ui') reactTriggerChange(selectState[0]) - const cancelButtonInEdit = await queryAsync($, '.btn-secondary--lg.page-container__footer-button') + const cancelButtonInEdit = await queryAsync($, '.btn-default.btn--large.page-container__footer-button') cancelButtonInEdit[0].click() // sendButtonInEdit[0].click() diff --git a/test/screens/new-ui.js b/test/screens/new-ui.js index 65a542e49..e3ba7f6ab 100644 --- a/test/screens/new-ui.js +++ b/test/screens/new-ui.js @@ -163,7 +163,7 @@ async function captureAllScreens() { await delay(300) await captureLanguageScreenShots('metamask account detail export private key screen - password entered') - await driver.findElement(By.css('.btn-primary--lg.export-private-key__button')).click() + await driver.findElement(By.css('.btn-primary.btn--large.export-private-key__button')).click() await delay(300) await captureLanguageScreenShots('metamask account detail export private key screen - reveal key') diff --git a/ui/app/actions.js b/ui/app/actions.js index 649f740e9..a9372d6f3 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -503,17 +503,23 @@ function requestRevealSeedWords (password) { } function resetAccount () { - return (dispatch) => { - background.resetAccount((err, account) => { - dispatch(actions.hideLoadingIndication()) - if (err) { - dispatch(actions.displayWarning(err.message)) - } + return dispatch => { + dispatch(actions.showLoadingIndication()) - log.info('Transaction history reset for ' + account) - dispatch(actions.showAccountsPage()) - }) - } + return new Promise((resolve, reject) => { + background.resetAccount((err, account) => { + dispatch(actions.hideLoadingIndication()) + if (err) { + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + + log.info('Transaction history reset for ' + account) + dispatch(actions.showAccountsPage()) + resolve(account) + }) + }) + } } function addNewKeyring (type, opts) { diff --git a/ui/app/components/button/button.component.js b/ui/app/components/button/button.component.js index fe3bf363c..e8e798445 100644 --- a/ui/app/components/button/button.component.js +++ b/ui/app/components/button/button.component.js @@ -2,20 +2,15 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' -const SECONDARY = 'secondary' +const CLASSNAME_DEFAULT = 'btn-default' const CLASSNAME_PRIMARY = 'btn-primary' -const CLASSNAME_PRIMARY_LARGE = 'btn-primary--lg' const CLASSNAME_SECONDARY = 'btn-secondary' -const CLASSNAME_SECONDARY_LARGE = 'btn-secondary--lg' +const CLASSNAME_LARGE = 'btn--large' -const getClassName = (type, large = false) => { - let output = type === SECONDARY ? CLASSNAME_SECONDARY : CLASSNAME_PRIMARY - - if (large) { - output += ` ${type === SECONDARY ? CLASSNAME_SECONDARY_LARGE : CLASSNAME_PRIMARY_LARGE}` - } - - return output +const typeHash = { + default: CLASSNAME_DEFAULT, + primary: CLASSNAME_PRIMARY, + secondary: CLASSNAME_SECONDARY, } class Button extends Component { @@ -24,7 +19,11 @@ class Button extends Component { return ( { this.props.children } diff --git a/ui/app/components/button/button.stories.js b/ui/app/components/button/button.stories.js index d1e14e869..dec084a25 100644 --- a/ui/app/components/button/button.stories.js +++ b/ui/app/components/button/button.stories.js @@ -13,13 +13,21 @@ storiesOf('Button', module) {text('text', 'Click me')} ) - .add('secondary', () => ( + .add('secondary', () => {text('text', 'Click me')} + ) + .add('default', () => ( + + {text('text', 'Click me')} + )) .add('large primary', () => ( )) + .add('large default', () => ( + + {text('text', 'Click me')} + + )) diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 1ff8eea87..e3529041b 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -308,7 +308,7 @@ CustomizeGasModal.prototype.render = function () { }, [this.context.t('revert')]), h('div.send-v2__customize-gas__buttons', [ - h('button.btn-secondary.send-v2__customize-gas__cancel', { + h('button.btn-default.send-v2__customize-gas__cancel', { onClick: this.props.hideModal, style: { marginRight: '10px', diff --git a/ui/app/components/modals/confirm-reset-account/confirm-reset-account.component.js b/ui/app/components/modals/confirm-reset-account/confirm-reset-account.component.js new file mode 100644 index 000000000..14a4da62a --- /dev/null +++ b/ui/app/components/modals/confirm-reset-account/confirm-reset-account.component.js @@ -0,0 +1,54 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import Button from '../../button' + +class ConfirmResetAccount extends Component { + static propTypes = { + hideModal: PropTypes.func.isRequired, + resetAccount: PropTypes.func.isRequired, + } + + static contextTypes = { + t: PropTypes.func, + } + + handleReset () { + this.props.resetAccount() + .then(() => this.props.hideModal()) + } + + render () { + const { t } = this.context + + return ( + + + + { `${t('resetAccount')}?` } + + + { t('resetAccountDescription') } + + + + this.props.hideModal()} + > + { t('nevermind') } + + this.handleReset()} + > + { t('reset') } + + + + ) + } +} + +export default ConfirmResetAccount diff --git a/ui/app/components/modals/confirm-reset-account/confirm-reset-account.container.js b/ui/app/components/modals/confirm-reset-account/confirm-reset-account.container.js new file mode 100644 index 000000000..9630a5593 --- /dev/null +++ b/ui/app/components/modals/confirm-reset-account/confirm-reset-account.container.js @@ -0,0 +1,13 @@ +import { connect } from 'react-redux' +import ConfirmResetAccount from './confirm-reset-account.component' + +const { hideModal, resetAccount } = require('../../../actions') + +const mapDispatchToProps = dispatch => { + return { + hideModal: () => dispatch(hideModal()), + resetAccount: () => dispatch(resetAccount()), + } +} + +export default connect(null, mapDispatchToProps)(ConfirmResetAccount) diff --git a/ui/app/components/modals/confirm-reset-account/index.js b/ui/app/components/modals/confirm-reset-account/index.js new file mode 100644 index 000000000..c812ffc55 --- /dev/null +++ b/ui/app/components/modals/confirm-reset-account/index.js @@ -0,0 +1,2 @@ +import ConfirmResetAccount from './confirm-reset-account.container' +module.exports = ConfirmResetAccount diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js index ad5f9b695..2daa7fa1d 100644 --- a/ui/app/components/modals/deposit-ether-modal.js +++ b/ui/app/components/modals/deposit-ether-modal.js @@ -109,7 +109,7 @@ DepositEtherModal.prototype.renderRow = function ({ ]), !hideButton && h('div.deposit-ether-modal__buy-row__button', [ - h('button.btn-primary--lg.deposit-ether-modal__deposit-button', { + h('button.btn-primary.btn--large.deposit-ether-modal__deposit-button', { onClick: onButtonClick, }, [buttonLabel]), ]), diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 447e43b7a..80ece425f 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -87,14 +87,14 @@ ExportPrivateKeyModal.prototype.renderButton = function (className, onClick, lab ExportPrivateKeyModal.prototype.renderButtons = function (privateKey, password, address, hideModal) { return h('div.export-private-key-buttons', {}, [ !privateKey && this.renderButton( - 'btn-secondary--lg export-private-key__button export-private-key__button--cancel', + 'btn-default btn--large export-private-key__button export-private-key__button--cancel', () => hideModal(), 'Cancel' ), (privateKey - ? this.renderButton('btn-primary--lg export-private-key__button', () => hideModal(), this.context.t('done')) - : this.renderButton('btn-primary--lg export-private-key__button', () => this.exportAccountAndGetPrivateKey(this.state.password, address), this.context.t('confirm')) + ? this.renderButton('btn-primary btn--large export-private-key__button', () => hideModal(), this.context.t('done')) + : this.renderButton('btn-primary btn--large export-private-key__button', () => this.exportAccountAndGetPrivateKey(this.state.password, address), this.context.t('confirm')) ), ]) diff --git a/ui/app/components/modals/index.scss b/ui/app/components/modals/index.scss index ec6207f7e..ad6fe16d3 100644 --- a/ui/app/components/modals/index.scss +++ b/ui/app/components/modals/index.scss @@ -1 +1,52 @@ -@import './transaction-confirmed/index'; +.modal-container { + width: 100%; + height: 100%; + background-color: #fff; + display: flex; + flex-flow: column; + border-radius: 8px; + + &__title { + font-size: 1.5rem; + font-weight: 500; + padding: 16px 0; + text-align: center; + } + + &__description { + text-align: center; + font-size: .875rem; + } + + &__content { + overflow-y: auto; + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + padding: 32px; + + @media screen and (max-width: 575px) { + justify-content: center; + padding: 28px 20px; + } + } + + &__footer { + display: flex; + flex-flow: row; + justify-content: center; + border-top: 1px solid #d2d8dd; + padding: 16px; + flex: 0 0 auto; + + &-button { + min-width: 0; + margin-right: 16px; + + &:last-of-type { + margin-right: 0; + } + } + } +} diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 841189277..85e85597a 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -19,8 +19,30 @@ 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 ConfirmResetAccount = require('./notification-modals/confirm-reset-account') +const ConfirmResetAccount = require('./confirm-reset-account') const TransactionConfirmed = require('./transaction-confirmed') +const WelcomeBeta = require('./welcome-beta') +const Notification = require('./notification') + +const modalContainerBaseStyle = { + transform: 'translate3d(-50%, 0, 0px)', + border: '1px solid #CCCFD1', + borderRadius: '8px', + backgroundColor: '#FFFFFF', + boxShadow: '0 2px 22px 0 rgba(0,0,0,0.2)', +} + +const modalContainerLaptopStyle = { + ...modalContainerBaseStyle, + width: '344px', + top: '15%', +} + +const modalContainerMobileStyle = { + ...modalContainerBaseStyle, + width: '309px', + top: '12.5%', +} const accountModalStyle = { mobileModalStyle: { @@ -174,18 +196,18 @@ const MODALS = { BETA_UI_NOTIFICATION_MODAL: { contents: [ - h(NotifcationModal, { - header: 'uiWelcome', - message: 'uiWelcomeMessage', - }), + h(Notification, [ + h(WelcomeBeta), + ]), ], mobileModalStyle: { - width: '95%', - top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', + ...modalContainerMobileStyle, }, laptopModalStyle: { - width: '449px', - top: 'calc(33% + 45px)', + ...modalContainerLaptopStyle, + }, + contentStyle: { + borderRadius: '8px', }, }, @@ -209,12 +231,13 @@ const MODALS = { CONFIRM_RESET_ACCOUNT: { contents: h(ConfirmResetAccount), mobileModalStyle: { - width: '95%', - top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', + ...modalContainerMobileStyle, }, laptopModalStyle: { - width: '473px', - top: 'calc(33% + 45px)', + ...modalContainerLaptopStyle, + }, + contentStyle: { + borderRadius: '8px', }, }, @@ -269,31 +292,18 @@ const MODALS = { TRANSACTION_CONFIRMED: { disableBackdropClick: true, contents: [ - h(TransactionConfirmed, {}, []), + h(Notification, [ + h(TransactionConfirmed), + ]), ], mobileModalStyle: { - width: '100%', - height: '100%', - transform: 'none', - left: '0', - right: '0', - margin: '0 auto', - boxShadow: '0 0 7px 0 rgba(0,0,0,0.08)', - top: '0', - display: 'flex', + ...modalContainerMobileStyle, }, laptopModalStyle: { - width: '344px', - transform: 'translate3d(-50%, 0, 0px)', - top: '15%', - border: '1px solid #CCCFD1', - borderRadius: '8px', - backgroundColor: '#FFFFFF', - boxShadow: '0 2px 22px 0 rgba(0,0,0,0.2)', + ...modalContainerLaptopStyle, }, contentStyle: { borderRadius: '8px', - height: '100%', }, }, diff --git a/ui/app/components/modals/notification-modals/confirm-reset-account.js b/ui/app/components/modals/notification-modals/confirm-reset-account.js deleted file mode 100644 index 89fa9bef1..000000000 --- a/ui/app/components/modals/notification-modals/confirm-reset-account.js +++ /dev/null @@ -1,46 +0,0 @@ -const { Component } = require('react') -const PropTypes = require('prop-types') -const h = require('react-hyperscript') -const connect = require('react-redux').connect -const actions = require('../../../actions') -const NotifcationModal = require('../notification-modal') - -class ConfirmResetAccount extends Component { - render () { - const { resetAccount } = this.props - - return h(NotifcationModal, { - header: 'Are you sure you want to reset account?', - message: h('div', [ - - h('span', `Resetting is for developer use only. This button wipes the current account's transaction history, - which is used to calculate the current account nonce. `), - - h('a.notification-modal__link', { - href: 'http://metamask.helpscoutdocs.com/article/36-resetting-an-account', - target: '_blank', - onClick (event) { global.platform.openWindow({ url: event.target.href }) }, - }, 'Read more.'), - - ]), - showCancelButton: true, - showConfirmButton: true, - onConfirm: resetAccount, - - }) - } -} - -ConfirmResetAccount.propTypes = { - resetAccount: PropTypes.func, -} - -const mapDispatchToProps = dispatch => { - return { - resetAccount: () => { - dispatch(actions.resetAccount()) - }, - } -} - -module.exports = connect(null, mapDispatchToProps)(ConfirmResetAccount) diff --git a/ui/app/components/modals/notification/index.js b/ui/app/components/modals/notification/index.js new file mode 100644 index 000000000..d60a3129b --- /dev/null +++ b/ui/app/components/modals/notification/index.js @@ -0,0 +1,2 @@ +import Notification from './notification.container' +module.exports = Notification diff --git a/ui/app/components/modals/notification/notification.component.js b/ui/app/components/modals/notification/notification.component.js new file mode 100644 index 000000000..1af2f3ca8 --- /dev/null +++ b/ui/app/components/modals/notification/notification.component.js @@ -0,0 +1,30 @@ +import React from 'react' +import PropTypes from 'prop-types' +import Button from '../../button' + +const Notification = (props, context) => { + return ( + + { props.children } + + props.onHide()} + > + { context.t('ok') } + + + + ) +} + +Notification.propTypes = { + onHide: PropTypes.func.isRequired, + children: PropTypes.element, +} + +Notification.contextTypes = { + t: PropTypes.func, +} + +export default Notification diff --git a/ui/app/components/modals/notification/notification.container.js b/ui/app/components/modals/notification/notification.container.js new file mode 100644 index 000000000..5b98714da --- /dev/null +++ b/ui/app/components/modals/notification/notification.container.js @@ -0,0 +1,38 @@ +import { connect } from 'react-redux' +import Notification from './notification.component' + +const { hideModal } = require('../../../actions') + +const mapStateToProps = state => { + const { appState: { modal: { modalState: { props } } } } = state + const { onHide } = props + return { + onHide, + } +} + +const mapDispatchToProps = dispatch => { + return { + hideModal: () => dispatch(hideModal()), + } +} + +const mergeProps = (stateProps, dispatchProps, ownProps) => { + const { onHide, ...otherStateProps } = stateProps + const { hideModal, ...otherDispatchProps } = dispatchProps + + return { + ...otherStateProps, + ...otherDispatchProps, + ...ownProps, + onHide: () => { + hideModal() + + if (onHide && typeof onHide === 'function') { + onHide() + } + }, + } +} + +export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(Notification) diff --git a/ui/app/components/modals/transaction-confirmed/index.js b/ui/app/components/modals/transaction-confirmed/index.js index c8db91388..cee8da7f8 100644 --- a/ui/app/components/modals/transaction-confirmed/index.js +++ b/ui/app/components/modals/transaction-confirmed/index.js @@ -1,2 +1,2 @@ -import TransactionConfirmed from './transaction-confirmed.container' +import TransactionConfirmed from './transaction-confirmed.component' module.exports = TransactionConfirmed diff --git a/ui/app/components/modals/transaction-confirmed/index.scss b/ui/app/components/modals/transaction-confirmed/index.scss deleted file mode 100644 index f8cd1f212..000000000 --- a/ui/app/components/modals/transaction-confirmed/index.scss +++ /dev/null @@ -1,21 +0,0 @@ -.transaction-confirmed { - display: flex; - flex-direction: column; - align-items: center; - padding: 32px; - - &__title { - font-size: 2rem; - padding: 16px 0; - } - - &__description { - text-align: center; - font-size: .875rem; - line-height: 1.5rem; - } - - @media screen and (max-width: 575px) { - justify-content: center; - } -} diff --git a/ui/app/components/modals/transaction-confirmed/transaction-confirmed.component.js b/ui/app/components/modals/transaction-confirmed/transaction-confirmed.component.js index 8d3b288ae..c1c8a2976 100644 --- a/ui/app/components/modals/transaction-confirmed/transaction-confirmed.component.js +++ b/ui/app/components/modals/transaction-confirmed/transaction-confirmed.component.js @@ -1,42 +1,20 @@ -import React, { Component } from 'react' +import React from 'react' import PropTypes from 'prop-types' -import Button from '../../button' -class TransactionConfirmed extends Component { - render () { - const { t } = this.context +const TransactionConfirmed = (props, context) => { + const { t } = context - return ( - - - - - { `${t('confirmed')}!` } - - - { t('initialTransactionConfirmed') } - - - - { - this.props.hideModal() - this.props.onHide() - }} - > - { t('ok') } - - + return ( + + + + { `${t('confirmed')}!` } - ) - } -} - -TransactionConfirmed.propTypes = { - hideModal: PropTypes.func.isRequired, - onHide: PropTypes.func.isRequired, + + { t('initialTransactionConfirmed') } + + + ) } TransactionConfirmed.contextTypes = { diff --git a/ui/app/components/modals/transaction-confirmed/transaction-confirmed.container.js b/ui/app/components/modals/transaction-confirmed/transaction-confirmed.container.js deleted file mode 100644 index 63872f7f2..000000000 --- a/ui/app/components/modals/transaction-confirmed/transaction-confirmed.container.js +++ /dev/null @@ -1,20 +0,0 @@ -import { connect } from 'react-redux' -import TransactionConfirmed from './transaction-confirmed.component' - -const { hideModal } = require('../../../actions') - -const mapStateToProps = state => { - const { appState: { modal: { modalState: { props } } } } = state - const { onHide } = props - return { - onHide, - } -} - -const mapDispatchToProps = dispatch => { - return { - hideModal: () => dispatch(hideModal()), - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(TransactionConfirmed) diff --git a/ui/app/components/modals/welcome-beta/index.js b/ui/app/components/modals/welcome-beta/index.js new file mode 100644 index 000000000..515c9cdaf --- /dev/null +++ b/ui/app/components/modals/welcome-beta/index.js @@ -0,0 +1,2 @@ +import WelcomeBeta from './welcome-beta.component' +module.exports = WelcomeBeta diff --git a/ui/app/components/modals/welcome-beta/welcome-beta.component.js b/ui/app/components/modals/welcome-beta/welcome-beta.component.js new file mode 100644 index 000000000..61571723a --- /dev/null +++ b/ui/app/components/modals/welcome-beta/welcome-beta.component.js @@ -0,0 +1,23 @@ +import React from 'react' +import PropTypes from 'prop-types' + +const TransactionConfirmed = (props, context) => { + const { t } = context + + return ( + + + { `${t('uiWelcome')}` } + + + { t('uiWelcomeMessage') } + + + ) +} + +TransactionConfirmed.contextTypes = { + t: PropTypes.func, +} + +export default TransactionConfirmed diff --git a/ui/app/components/pages/add-token/add-token.component.js b/ui/app/components/pages/add-token/add-token.component.js index 0677b4317..1f4b37b53 100644 --- a/ui/app/components/pages/add-token/add-token.component.js +++ b/ui/app/components/pages/add-token/add-token.component.js @@ -323,7 +323,7 @@ class AddToken extends Component { { diff --git a/ui/app/components/pages/confirm-add-token/confirm-add-token.component.js b/ui/app/components/pages/confirm-add-token/confirm-add-token.component.js index 9db9efc37..65d654b92 100644 --- a/ui/app/components/pages/confirm-add-token/confirm-add-token.component.js +++ b/ui/app/components/pages/confirm-add-token/confirm-add-token.component.js @@ -87,7 +87,7 @@ export default class ConfirmAddToken extends Component { history.push(ADD_TOKEN_ROUTE)} diff --git a/ui/app/components/pages/create-account/import-account/json.js b/ui/app/components/pages/create-account/import-account/json.js index 0a3314b2a..0164417ec 100644 --- a/ui/app/components/pages/create-account/import-account/json.js +++ b/ui/app/components/pages/create-account/import-account/json.js @@ -51,7 +51,7 @@ class JsonImportSubview extends Component { h('div.new-account-create-form__buttons', {}, [ - h('button.btn-secondary.new-account-create-form__button', { + h('button.btn-default.new-account-create-form__button', { onClick: () => this.props.history.push(DEFAULT_ROUTE), }, [ this.context.t('cancel'), @@ -105,7 +105,7 @@ class JsonImportSubview extends Component { } this.props.importNewJsonAccount([ fileContents, password ]) - // JS runtime requires caught rejections but failures are handled by Redux + // JS runtime requires caught rejections but failures are handled by Redux .catch() } } diff --git a/ui/app/components/pages/create-account/import-account/private-key.js b/ui/app/components/pages/create-account/import-account/private-key.js index df7ac910a..e55a47a3c 100644 --- a/ui/app/components/pages/create-account/import-account/private-key.js +++ b/ui/app/components/pages/create-account/import-account/private-key.js @@ -59,13 +59,13 @@ PrivateKeyImportView.prototype.render = function () { h('div.new-account-import-form__buttons', {}, [ - h('button.btn-secondary--lg.new-account-create-form__button', { + h('button.btn-default.btn--large.new-account-create-form__button', { onClick: () => this.props.history.push(DEFAULT_ROUTE), }, [ this.context.t('cancel'), ]), - h('button.btn-primary--lg.new-account-create-form__button', { + h('button.btn-primary.btn--large.new-account-create-form__button', { onClick: () => this.createNewKeychain(), }, [ this.context.t('import'), @@ -91,7 +91,7 @@ PrivateKeyImportView.prototype.createNewKeychain = function () { const { importNewAccount, history } = this.props importNewAccount('Private Key', [ privateKey ]) - // JS runtime requires caught rejections but failures are handled by Redux + // JS runtime requires caught rejections but failures are handled by Redux .catch() .then(() => history.push(DEFAULT_ROUTE)) } diff --git a/ui/app/components/pages/create-account/new-account.js b/ui/app/components/pages/create-account/new-account.js index 03a5ee72d..9c94990e0 100644 --- a/ui/app/components/pages/create-account/new-account.js +++ b/ui/app/components/pages/create-account/new-account.js @@ -38,13 +38,13 @@ class NewAccountCreateForm extends Component { h('div.new-account-create-form__buttons', {}, [ - h('button.btn-secondary--lg.new-account-create-form__button', { + h('button.btn-default.btn--large.new-account-create-form__button', { onClick: () => history.push(DEFAULT_ROUTE), }, [ this.context.t('cancel'), ]), - h('button.btn-primary--lg.new-account-create-form__button', { + h('button.btn-primary.btn--large.new-account-create-form__button', { onClick: () => { createAccount(newAccountName || defaultAccountName) .then(() => history.push(DEFAULT_ROUTE)) diff --git a/ui/app/components/pages/keychains/reveal-seed.js b/ui/app/components/pages/keychains/reveal-seed.js index 685c81074..7d7d3f462 100644 --- a/ui/app/components/pages/keychains/reveal-seed.js +++ b/ui/app/components/pages/keychains/reveal-seed.js @@ -106,10 +106,10 @@ class RevealSeedPage extends Component { renderPasswordPromptFooter () { return ( h('.page-container__footer', [ - h('button.btn-secondary--lg.page-container__footer-button', { + h('button.btn-default.btn--large.page-container__footer-button', { onClick: () => this.props.history.push(DEFAULT_ROUTE), }, this.context.t('cancel')), - h('button.btn-primary--lg.page-container__footer-button', { + h('button.btn-primary.btn--large.page-container__footer-button', { onClick: event => this.handleSubmit(event), disabled: this.state.password === '', }, this.context.t('next')), @@ -120,7 +120,7 @@ class RevealSeedPage extends Component { renderRevealSeedFooter () { return ( h('.page-container__footer', [ - h('button.btn-secondary--lg.page-container__footer-button', { + h('button.btn-default.btn--large.page-container__footer-button', { onClick: () => this.props.history.push(DEFAULT_ROUTE), }, this.context.t('close')), ]) diff --git a/ui/app/components/pages/settings/settings.js b/ui/app/components/pages/settings/settings.js index f58ac7ddf..ff42a13de 100644 --- a/ui/app/components/pages/settings/settings.js +++ b/ui/app/components/pages/settings/settings.js @@ -217,7 +217,7 @@ class Settings extends Component { ]), h('div.settings__content-item', [ h('div.settings__content-item-col', [ - h('button.btn-primary--lg.settings__button', { + h('button.btn-primary.btn--large.settings__button', { onClick (event) { window.logStateString((err, result) => { if (err) { @@ -242,7 +242,7 @@ class Settings extends Component { h('div.settings__content-item', this.context.t('revealSeedWords')), h('div.settings__content-item', [ h('div.settings__content-item-col', [ - h('button.btn-primary--lg.settings__button--red', { + h('button.btn-primary.btn--large.settings__button--red', { onClick: event => { event.preventDefault() history.push(REVEAL_SEED_ROUTE) @@ -262,7 +262,7 @@ class Settings extends Component { h('div.settings__content-item', this.context.t('useOldUI')), h('div.settings__content-item', [ h('div.settings__content-item-col', [ - h('button.btn-primary--lg.settings__button--orange', { + h('button.btn-primary.btn--large.settings__button--orange', { onClick (event) { event.preventDefault() setFeatureFlagToBeta() @@ -281,7 +281,7 @@ class Settings extends Component { h('div.settings__content-item', this.context.t('resetAccount')), h('div.settings__content-item', [ h('div.settings__content-item-col', [ - h('button.btn-primary--lg.settings__button--orange', { + h('button.btn-primary.btn--large.settings__button--orange', { onClick (event) { event.preventDefault() showResetAccountConfirmationModal() diff --git a/ui/app/components/shapeshift-form.js b/ui/app/components/shapeshift-form.js index 22ab64426..93d2023b5 100644 --- a/ui/app/components/shapeshift-form.js +++ b/ui/app/components/shapeshift-form.js @@ -242,7 +242,7 @@ ShapeshiftForm.prototype.render = function () { ]), - !depositAddress && h('button.btn-primary--lg.shapeshift-form__shapeshift-buy-btn', { + !depositAddress && h('button.btn-primary.btn--large.shapeshift-form__shapeshift-buy-btn', { className: btnClass, disabled: !token, onClick: () => this.onBuyWithShapeShift(), diff --git a/ui/app/components/signature-request.js b/ui/app/components/signature-request.js index 474fcf439..ab780dcf4 100644 --- a/ui/app/components/signature-request.js +++ b/ui/app/components/signature-request.js @@ -235,12 +235,12 @@ SignatureRequest.prototype.renderFooter = function () { } return h('div.request-signature__footer', [ - h('button.btn-secondary--lg.request-signature__footer__cancel-button', { + h('button.btn-default.btn--large.request-signature__footer__cancel-button', { onClick: event => { cancel(event).then(() => this.props.history.push(DEFAULT_ROUTE)) }, }, this.context.t('cancel')), - h('button.btn-primary--lg', { + h('button.btn-primary.btn--large', { onClick: event => { sign(event).then(() => this.props.history.push(DEFAULT_ROUTE)) }, diff --git a/ui/app/css/itcss/components/buttons.scss b/ui/app/css/itcss/components/buttons.scss index 4cbed6093..f93daec04 100644 --- a/ui/app/css/itcss/components/buttons.scss +++ b/ui/app/css/itcss/components/buttons.scss @@ -2,10 +2,10 @@ Buttons */ +.btn-default, .btn-primary, -.btn-primary--lg, -.btn-secondary, -.btn-secondary--lg { +.btn-secondary { + height: 44px; background: $white; display: flex; justify-content: center; @@ -20,10 +20,16 @@ width: 100%; text-transform: uppercase; outline: none; + + &--disabled, + &[disabled] { + cursor: auto; + opacity: .5; + pointer-events: none; + } } -.btn-primary, -.btn-primary--lg { +.btn-primary { color: $curious-blue; border: 2px solid $spindle; @@ -35,17 +41,23 @@ &:hover { border-color: $curious-blue; } +} - &--disabled, - &[disabled] { - cursor: auto; - opacity: .5; - pointer-events: none; +.btn-secondary { + color: $monzo; + border: 2px solid lighten($monzo, 40%); + + &:active { + background: lighten($monzo, 55%); + border-color: $monzo; + } + + &:hover { + border-color: $monzo; } } -.btn-secondary, -.btn-secondary--lg { +.btn-default { color: $scorpion; border: 2px solid $dusty-gray; @@ -57,20 +69,9 @@ &:hover { border-color: $scorpion; } - - &--disabled, - &[disabled] { - cursor: auto; - opacity: .5; - pointer-events: none; - } -} - -.btn-primary, .btn-secondary { - height: 44px; } -.btn-primary--lg, .btn-secondary--lg { +.btn--large { height: 54px; } diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 6736b5571..4fbe8ff11 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -499,7 +499,7 @@ SendTransactionScreen.prototype.renderFooter = function () { return h('div.page-container__footer', [ h(Button, { - type: 'secondary', + type: 'default', large: true, className: 'page-container__footer-button', onClick: () => {