diff options
author | Alexander Tseung <alextsg@gmail.com> | 2018-03-27 15:20:35 +0800 |
---|---|---|
committer | Alexander Tseung <alextsg@gmail.com> | 2018-03-27 15:20:35 +0800 |
commit | 6f367a5a6b4fb8918405f233293dc3f4840b4a3d (patch) | |
tree | c60c01300c90204f8634d1f3e9e79b4ecc2fceda /mascara/src | |
parent | 72ffa2c3f5abbcb06c8ab5fdf20b9d934c330692 (diff) | |
parent | e001c0900b5256c0c8769f0c3eb5d2007f5b18d3 (diff) | |
download | tangerine-wallet-browser-6f367a5a6b4fb8918405f233293dc3f4840b4a3d.tar tangerine-wallet-browser-6f367a5a6b4fb8918405f233293dc3f4840b4a3d.tar.gz tangerine-wallet-browser-6f367a5a6b4fb8918405f233293dc3f4840b4a3d.tar.bz2 tangerine-wallet-browser-6f367a5a6b4fb8918405f233293dc3f4840b4a3d.tar.lz tangerine-wallet-browser-6f367a5a6b4fb8918405f233293dc3f4840b4a3d.tar.xz tangerine-wallet-browser-6f367a5a6b4fb8918405f233293dc3f4840b4a3d.tar.zst tangerine-wallet-browser-6f367a5a6b4fb8918405f233293dc3f4840b4a3d.zip |
Fix merge conflicts
Diffstat (limited to 'mascara/src')
-rw-r--r-- | mascara/src/app/buy-ether-widget/index.js | 3 | ||||
-rw-r--r-- | mascara/src/app/first-time/breadcrumbs.js | 5 | ||||
-rw-r--r-- | mascara/src/app/first-time/buy-ether-screen.js | 3 | ||||
-rw-r--r-- | mascara/src/app/first-time/create-password-screen.js | 16 | ||||
-rw-r--r-- | mascara/src/app/first-time/import-account-screen.js | 3 | ||||
-rw-r--r-- | mascara/src/app/first-time/import-seed-phrase-screen.js | 205 | ||||
-rw-r--r-- | mascara/src/app/first-time/index.css | 219 | ||||
-rw-r--r-- | mascara/src/app/first-time/index.js | 48 | ||||
-rw-r--r-- | mascara/src/app/first-time/loading-screen.js | 10 | ||||
-rw-r--r-- | mascara/src/app/first-time/notice-screen.js | 55 | ||||
-rw-r--r-- | mascara/src/app/first-time/seed-screen.js | 43 | ||||
-rw-r--r-- | mascara/src/app/first-time/unique-image-screen.js | 37 | ||||
-rw-r--r-- | mascara/src/app/shapeshift-form/index.js | 3 |
13 files changed, 451 insertions, 199 deletions
diff --git a/mascara/src/app/buy-ether-widget/index.js b/mascara/src/app/buy-ether-widget/index.js index 9fe659daa..c60221a0a 100644 --- a/mascara/src/app/buy-ether-widget/index.js +++ b/mascara/src/app/buy-ether-widget/index.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import classnames from 'classnames' import {connect} from 'react-redux' import {qrcode} from 'qrcode-npm' diff --git a/mascara/src/app/first-time/breadcrumbs.js b/mascara/src/app/first-time/breadcrumbs.js index f8460d200..b81a9fb9b 100644 --- a/mascara/src/app/first-time/breadcrumbs.js +++ b/mascara/src/app/first-time/breadcrumbs.js @@ -1,10 +1,11 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' export default class Breadcrumbs extends Component { static propTypes = { total: PropTypes.number, - currentIndex: PropTypes.number + currentIndex: PropTypes.number, }; render() { diff --git a/mascara/src/app/first-time/buy-ether-screen.js b/mascara/src/app/first-time/buy-ether-screen.js index 45b2df1c8..c5a560638 100644 --- a/mascara/src/app/first-time/buy-ether-screen.js +++ b/mascara/src/app/first-time/buy-ether-screen.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import classnames from 'classnames' import {connect} from 'react-redux' import {qrcode} from 'qrcode-npm' diff --git a/mascara/src/app/first-time/create-password-screen.js b/mascara/src/app/first-time/create-password-screen.js index c490d8831..8fee04d1c 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -7,6 +7,7 @@ import Breadcrumbs from './breadcrumbs' import { DEFAULT_ROUTE, IMPORT_ACCOUNT_ROUTE } from '../../../../ui/app/routes' import EventEmitter from 'events' import Mascot from '../../../../ui/app/components/mascot' +import classnames from 'classnames' class CreatePasswordScreen extends Component { static propTypes = { @@ -15,6 +16,7 @@ class CreatePasswordScreen extends Component { history: PropTypes.object.isRequired, isInitialized: PropTypes.bool, isUnlocked: PropTypes.bool, + isMascara: PropTypes.bool.isRequired, } state = { @@ -61,15 +63,17 @@ class CreatePasswordScreen extends Component { } render () { - const { isLoading } = this.props + const { isLoading, isMascara } = this.props return isLoading ? <LoadingScreen loadingMessage="Creating your new account" /> : ( - <div> - <h2 className="alpha-warning">Warning: This is Experimental software and is a Developer BETA</h2> - <div className="first-view-main"> - <div className="mascara-info"> + <div className={classnames({ 'first-view-main-wrapper': !isMascara })}> + <div className={classnames({ + 'first-view-main': !isMascara, + 'first-view-main__mascara': isMascara, + })}> + {isMascara && <div className="mascara-info first-view-phone-invisible"> <Mascot animationEventEmitter={this.animationEventEmitter} width="225" @@ -81,7 +85,7 @@ class CreatePasswordScreen extends Component { <div className="info"> It allows you to hold ether & tokens, and interact with decentralized applications. </div> - </div> + </div>} <div className="create-password"> <div className="create-password__title"> Create Password diff --git a/mascara/src/app/first-time/import-account-screen.js b/mascara/src/app/first-time/import-account-screen.js index bf8e209e4..ab0aca0f0 100644 --- a/mascara/src/app/first-time/import-account-screen.js +++ b/mascara/src/app/first-time/import-account-screen.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import {connect} from 'react-redux' import classnames from 'classnames' import LoadingScreen from './loading-screen' diff --git a/mascara/src/app/first-time/import-seed-phrase-screen.js b/mascara/src/app/first-time/import-seed-phrase-screen.js index 2b01fa75d..86f02ceac 100644 --- a/mascara/src/app/first-time/import-seed-phrase-screen.js +++ b/mascara/src/app/first-time/import-seed-phrase-screen.js @@ -1,7 +1,13 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import {connect} from 'react-redux' -import LoadingScreen from './loading-screen' -import {createNewVaultAndRestore, hideWarning, displayWarning} from '../../../../ui/app/actions' +import classnames from 'classnames' +import { + createNewVaultAndRestore, + hideWarning, + displayWarning, + unMarkPasswordForgotten, +} from '../../../../ui/app/actions' class ImportSeedPhraseScreen extends Component { static propTypes = { @@ -10,8 +16,8 @@ class ImportSeedPhraseScreen extends Component { next: PropTypes.func.isRequired, createNewVaultAndRestore: PropTypes.func.isRequired, hideWarning: PropTypes.func.isRequired, - isLoading: PropTypes.bool.isRequired, displayWarning: PropTypes.func, + leaveImportSeedScreenState: PropTypes.func, }; state = { @@ -20,98 +26,137 @@ class ImportSeedPhraseScreen extends Component { confirmPassword: '', } - onClick = () => { - const { password, seedPhrase, confirmPassword } = this.state - const { createNewVaultAndRestore, next, displayWarning } = this.props + parseSeedPhrase = (seedPhrase) => { + return seedPhrase + .match(/\w+/g) + .join(' ') + } - if (seedPhrase.split(' ').length !== 12) { - this.warning = 'Seed Phrases are 12 words long' - displayWarning(this.warning) - return - } + onChange = ({ seedPhrase, password, confirmPassword }) => { + const { + password: prevPassword, + confirmPassword: prevConfirmPassword, + } = this.state + const { displayWarning, hideWarning } = this.props + + let warning = null - if (password.length < 8) { - this.warning = 'Passwords require a mimimum length of 8' - displayWarning(this.warning) - return + if (seedPhrase && this.parseSeedPhrase(seedPhrase).split(' ').length !== 12) { + warning = 'Seed Phrases are 12 words long' + } else if (password && password.length < 8) { + warning = 'Passwords require a mimimum length of 8' + } else if ((password || prevPassword) !== (confirmPassword || prevConfirmPassword)) { + warning = 'Confirmed password does not match' } - if (password !== confirmPassword) { - this.warning = 'Confirmed password does not match' - displayWarning(this.warning) - return + if (warning) { + displayWarning(warning) + } else { + hideWarning() } - this.warning = null - createNewVaultAndRestore(password, seedPhrase) + + seedPhrase && this.setState({ seedPhrase }) + password && this.setState({ password }) + confirmPassword && this.setState({ confirmPassword }) + } + + onClick = () => { + const { password, seedPhrase } = this.state + const { + createNewVaultAndRestore, + next, + displayWarning, + leaveImportSeedScreenState, + } = this.props + + leaveImportSeedScreenState() + createNewVaultAndRestore(password, this.parseSeedPhrase(seedPhrase)) .then(next) } render () { - return this.props.isLoading - ? <LoadingScreen loadingMessage="Creating your new account" /> - : ( - <div className="import-account"> - <a - className="import-account__back-button" - onClick={e => { - e.preventDefault() - this.props.back() - }} - href="#" - > - {`< Back`} - </a> - <div className="import-account__title"> - Import an Account with Seed Phrase - </div> - <div className="import-account__selector-label"> - Enter your secret twelve word phrase here to restore your vault. - </div> - <div className="import-account__input-wrapper"> - <label className="import-account__input-label">Wallet Seed</label> - <textarea - className="import-account__secret-phrase" - onChange={e => this.setState({seedPhrase: e.target.value})} - placeholder="Separate each word with a single space" - /> - </div> - <span - className="error" - > - {this.props.warning} - </span> - <div className="import-account__input-wrapper"> - <label className="import-account__input-label">New Password</label> - <input - className="first-time-flow__input" - type="password" - placeholder="New Password (min 8 characters)" - onChange={e => this.setState({password: e.target.value})} - /> - </div> - <div className="import-account__input-wrapper"> - <label className="import-account__input-label">Confirm Password</label> - <input - className="first-time-flow__input" - type="password" - placeholder="Confirm Password" - onChange={e => this.setState({confirmPassword: e.target.value})} - /> + const { seedPhrase, password, confirmPassword } = this.state + const { warning } = this.props + const importDisabled = warning || !seedPhrase || !password || !confirmPassword + return ( + <div className="first-view-main-wrapper"> + <div className="first-view-main"> + <div className="import-account"> + <a + className="import-account__back-button" + onClick={e => { + e.preventDefault() + this.props.back() + }} + href="#" + > + {`< Back`} + </a> + <div className="import-account__title"> + Import an Account with Seed Phrase + </div> + <div className="import-account__selector-label"> + Enter your secret twelve word phrase here to restore your vault. + </div> + <div className="import-account__input-wrapper"> + <label className="import-account__input-label">Wallet Seed</label> + <textarea + className="import-account__secret-phrase" + onChange={e => this.onChange({seedPhrase: e.target.value})} + value={this.state.seedPhrase} + placeholder="Separate each word with a single space" + /> + </div> + <span + className="error" + > + {this.props.warning} + </span> + <div className="import-account__input-wrapper"> + <label className="import-account__input-label">New Password</label> + <input + className="first-time-flow__input" + type="password" + placeholder="New Password (min 8 characters)" + onChange={e => this.onChange({password: e.target.value})} + /> + </div> + <div className="import-account__input-wrapper"> + <label + className={classnames('import-account__input-label', { + 'import-account__input-label__disabled': password.length < 8, + })} + >Confirm Password</label> + <input + className={classnames('first-time-flow__input', { + 'first-time-flow__input__disabled': password.length < 8, + })} + type="password" + placeholder="Confirm Password" + onChange={e => this.onChange({confirmPassword: e.target.value})} + disabled={password.length < 8} + /> + </div> + <button + className="first-time-flow__button" + onClick={() => !importDisabled && this.onClick()} + disabled={importDisabled} + > + Import + </button> </div> - <button - className="first-time-flow__button" - onClick={this.onClick} - > - Import - </button> </div> - ) + </div> + ) } } export default connect( - ({ appState: { isLoading, warning } }) => ({ isLoading, warning }), + ({ appState: { warning } }) => ({ warning }), dispatch => ({ + leaveImportSeedScreenState: () => { + dispatch(unMarkPasswordForgotten()) + }, createNewVaultAndRestore: (pw, seed) => dispatch(createNewVaultAndRestore(pw, seed)), displayWarning: (warning) => dispatch(displayWarning(warning)), hideWarning: () => dispatch(hideWarning()), diff --git a/mascara/src/app/first-time/index.css b/mascara/src/app/first-time/index.css index 4314efbe6..5f8bbd4be 100644 --- a/mascara/src/app/first-time/index.css +++ b/mascara/src/app/first-time/index.css @@ -1,29 +1,86 @@ +@font-face { + font-family: 'Roboto'; + font-style: normal; + font-weight: 400; + src: local('Roboto'), local('Roboto-Regular'), url('/fonts/Roboto/Roboto-Regular.ttf') format('truetype'); + unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; +} .first-time-flow { - height: 100vh; width: 100vw; - background-color: #FFF; + background-color: #fff; overflow: auto; + display: flex; + justify-content: center; + flex: 1 0 auto; + font-weight: 400; + font-family: Roboto; } -.alpha-warning { +.alpha-warning__container { + display: flex; + justify-content: center; background: #f7861c; +} + +.alpha-warning, +.alpha-warning-welcome-screen { color: #fff; line-height: 2em; - padding-left: 2em; } -.first-view-main { +@media screen and (min-width: 576px) { + .alpha-warning { + width: 85vw; + } +} + +@media screen and (min-width: 769px) { + .alpha-warning { + width: 80vw; + } +} + +@media screen and (min-width: 1281px) { + .alpha-warning { + width: 62vw; + } +} + +.alpha-warning-welcome-screen { + padding-left: 0; + text-align: center; +} + +.first-view-main-wrapper { display: flex; - flex-direction: row-reverse; + width: 100%; + height: 100%; + justify-content: center; + padding: 0 10px; +} + +.first-view-main, +.first-view-main__mascara { + display: flex; + flex-direction: row; + justify-content: flex-start; +} + +.first-view-main__mascara { justify-content: space-between; } +@media screen and (min-width: 1281px) { + .first-view-main { + width: 62vw; + } +} + .mascara-info { display: flex; flex-flow: column; margin-top: 70px; - margin-right: 10vw; width: 35vw; max-width: 550px; } @@ -44,8 +101,8 @@ .buy-ether { display: flex; flex-flow: column nowrap; - margin: 67px 0 50px 146px; - max-width: 35rem; + margin: 60px 0 30px 0; + position: relative; } .import-account { @@ -65,6 +122,10 @@ width: calc(100vw - 80px); } + .unique-image { + width: auto; + } + .create-password__title, .unique-image__title, .tou__title, @@ -76,6 +137,41 @@ width: initial !important; } + .alpha-warning, + .alpha-warning-welcome-screen { + line-height: 1em; + padding: 8px 12px; + } + + .first-view-main { + height: 100%; + flex-direction: column; + align-items: center; + justify-content: space-evenly; + margin-top: 12px; + } + + .mascara-info { + margin-top: 0px; + width: 100%; + align-items: center; + } + + .mascara-info .info { + text-align: center; + font-size: 16px; + margin: 0 10px; + padding-left: 0px; + } + + .mascara-info :first-child { + align-self: center; + } + + .first-view-phone-invisible { + display: none; + } + .first-time-flow__input { width: initial !important; font-size: 14px !important; @@ -129,10 +225,6 @@ max-width: 46rem; } -.backup-phrase { - max-width: 100%; -} - .create-password__title, .unique-image__title, .tou__title, @@ -175,11 +267,11 @@ color: #1B344D; font-size: 16px; line-height: 23px; - font-family: Montserrat UltraLight; + font-family: Roboto; } .buy-ether__small-body-text { - font-family: Montserrat UltraLight; + font-family: Roboto; height: 14px; color: #757575; font-size: 12px; @@ -207,7 +299,7 @@ height: 334px; overflow-y: auto; color: #757575; - font-family: Montserrat UltraLight; + font-family: Roboto; font-size: 12px; line-height: 15px; text-align: justify; @@ -216,7 +308,18 @@ .backup-phrase__content-wrapper { display: flex; - flex: row nowrap; + flex-flow: row wrap; + justify-content: space-between; +} + +.backup-phrase__phrase { + flex-grow: .5; + min-width: 0; +} + +.backup-phrase__next-button { + flex-grow: 1; + width: 100%; } .backup-phrase__body-text { @@ -224,15 +327,33 @@ } .backup-phrase__tips { - margin: 40px 85px; + margin-top: 40px; width: 285px; + flex-grow: .5; + min-width: 0; } .backup-phrase__tips-text { color: #5B5D67; font-size: 16px; line-height: 23px; - font-family: Montserrat UltraLight; + font-family: Roboto; + min-width: 0; +} + +@media only screen and (max-width: 768px) { + .backup-phrase__content-wrapper { + flex-direction: column; + } + + .backup-phrase__phrase { + flex: 1 0 auto; + } + + .backup-phrase__tips { + width: 100%; + flex: 1 0 auto; + } } .backup-phrase__secret { @@ -250,7 +371,7 @@ .backup-phrase__secret-words { width: 310px; color: #5B5D67; - font-family: Montserrat Light; + font-family: Roboto; font-size: 20px; line-height: 26px; text-align: center; @@ -279,7 +400,7 @@ background: none; box-shadow: none; color: #FFFFFF; - font-family: Montserrat Regular; + font-family: Roboto; font-size: 12px; font-weight: bold; line-height: 15px; @@ -289,13 +410,17 @@ } .backup-phrase__back-button, -.backup-phrase__back-button:hover, -.import-account__back-button, -.import-account__back-button:hover { +.import-account__back-button { margin-bottom: 18px; - color: #22232C; + color: #22232c; font-size: 16px; line-height: 21px; + position: absolute; + top: -25px; +} + +.backup-phrase__back-button { + top: -30px; } button.backup-phrase__reveal-button:hover { @@ -333,7 +458,7 @@ button.backup-phrase__reveal-button:hover { .backup-phrase__confirm-seed-option { color: #5B5D67; - font-family: Montserrat Light; + font-family: Roboto; font-size: 16px; line-height: 21px; background-color: #E7E7E7; @@ -355,7 +480,7 @@ button.backup-phrase__confirm-seed-option:hover { .import-account__faq-link { font-size: 18px; line-height: 23px; - font-family: Montserrat Light; + font-family: Roboto; } .import-account__selector-label { @@ -370,7 +495,7 @@ button.backup-phrase__confirm-seed-option:hover { background-color: #FFFFFF; margin-top: 14px; color: #5B5D67; - font-family: Montserrat Light; + font-family: Roboto; font-size: 18px; line-height: 23px; padding: 14px 21px; @@ -385,7 +510,7 @@ button.backup-phrase__confirm-seed-option:hover { font-size: 18px; line-height: 23px; margin-top: 21px; - font-family: Montserrat UltraLight; + font-family: Roboto; } .import-account__input-wrapper { @@ -413,6 +538,10 @@ button.backup-phrase__confirm-seed-option:hover { line-height: 23px; } +.import-account__input-label__disabled { + opacity: 0.5; +} + .import-account__input { width: 325px !important; } @@ -427,7 +556,7 @@ button.backup-phrase__confirm-seed-option:hover { border: 1px solid #1B344D; border-radius: 4px; color: #1B344D; - font-family: Montserrat Light; + font-family: Roboto; font-size: 18px; display: flex; flex-flow: column nowrap; @@ -444,7 +573,7 @@ button.backup-phrase__confirm-seed-option:hover { .import-account__file-name { color: #000000; - font-family: Montserrat Light; + font-family: Roboto; font-size: 18px; line-height: 23px; margin-left: 22px; @@ -465,7 +594,7 @@ button.backup-phrase__confirm-seed-option:hover { .buy-ether__content-headline { color: #1B344D; - font-family: Montserrat Light; + font-family: Roboto; font-size: 18px; line-height: 23px; } @@ -494,7 +623,7 @@ button.backup-phrase__confirm-seed-option:hover { align-items: center; padding: 20px 0; color: #9B9B9B; - font-family: Montserrat Light; + font-family: Roboto; font-size: 14px; line-height: 18px; cursor: pointer; @@ -529,7 +658,7 @@ button.backup-phrase__confirm-seed-option:hover { .buy-ether__button-separator-text { font-size: 20px; line-height: 26px; - font-family: Montserrat Light; + font-family: Roboto; margin: 35px 0 14px 30px; display: flex; flex-flow: column nowrap; @@ -541,11 +670,10 @@ button.backup-phrase__confirm-seed-option:hover { color: #1B344D !important; font-size: 14px !important; line-height: 18px !important; - font-family: Montserrat UltraLight !important; + font-family: Roboto; } .buy-ether__action-content-wrapper { - width: 360px; display: flex; flex-flow: column nowrap; } @@ -559,6 +687,10 @@ button.backup-phrase__confirm-seed-option:hover { background-color: #FFFFFF; } +.first-time-flow__input__disabled { + opacity: 0.5; +} + .first-time-flow__input::placeholder { color: #9B9B9B; font-weight: 200; @@ -571,6 +703,7 @@ button.backup-phrase__confirm-seed-option:hover { color: #FFFFFF; font-size: 20px; font-weight: 500; + font-family: Roboto; line-height: 26px; text-align: center; text-transform: uppercase; @@ -595,7 +728,7 @@ button.first-time-flow__button:hover { color: #1B344D; font-size: 20px; line-height: 26px; - font-family: Montserrat Light; + font-family: Roboto; text-align: center; margin: 35px 0 14px; background-color: transparent; @@ -647,7 +780,7 @@ button.first-time-flow__button--tertiary:hover { font-size: 20px; line-height: 26px; text-align: center; - font-family: Montserrat UltraLight; + font-family: Roboto; } .icon { @@ -695,7 +828,7 @@ button.first-time-flow__button--tertiary:hover { .shapeshift-form__deposit-instruction { color: #757575; color: rgba(0, 0, 0, 0.45); - font-family: Montserrat Light; + font-family: Roboto; font-weight: 300; line-height: 19px; padding-bottom: 6px; @@ -712,7 +845,7 @@ button.first-time-flow__button--tertiary:hover { width: 100%; height: 45px; line-height: 44px; - font-family: Montserrat Light; + font-family: Roboto; } .shapeshift-form__address-input-label { @@ -721,7 +854,7 @@ button.first-time-flow__button--tertiary:hover { font-weight: 500; line-height: 18px; padding-bottom: 6px; - font-family: Montserrat Light; + font-family: Roboto; } .shapeshift-form__address-input { @@ -740,7 +873,7 @@ button.first-time-flow__button--tertiary:hover { .shapeshift-form__address-input-error-message { color: #FF001F; - font-family: Montserrat Light; + font-family: Roboto; font-size: 12px; height: 24px; line-height: 18px; @@ -750,7 +883,7 @@ button.first-time-flow__button--tertiary:hover { display: flex; flex-flow: row wrap; color: #9B9B9B; - font-family: Montserrat Light; + font-family: Roboto; font-size: 10px; line-height: 16px; } diff --git a/mascara/src/app/first-time/index.js b/mascara/src/app/first-time/index.js index eec830ad2..b3494dec2 100644 --- a/mascara/src/app/first-time/index.js +++ b/mascara/src/app/first-time/index.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import {connect} from 'react-redux' import CreatePasswordScreen from './create-password-screen' import UniqueImageScreen from './unique-image-screen' @@ -6,7 +7,11 @@ import NoticeScreen from './notice-screen' import BackupPhraseScreen from './seed-screen' import ImportAccountScreen from './import-account-screen' import ImportSeedPhraseScreen from './import-seed-phrase-screen' -import {onboardingBuyEthView} from '../../../../ui/app/actions' +import { + onboardingBuyEthView, + unMarkPasswordForgotten, + showModal, +} from '../../../../ui/app/actions' class FirstTimeFlow extends Component { @@ -32,6 +37,7 @@ class FirstTimeFlow extends Component { NOTICE: 'notice', BACK_UP_PHRASE: 'back_up_phrase', CONFIRM_BACK_UP_PHRASE: 'confirm_back_up_phrase', + LOADING: 'loading', }; constructor (props) { @@ -50,11 +56,15 @@ class FirstTimeFlow extends Component { isInitialized, seedWords, noActiveNotices, + forgottenPassword, } = this.props const {SCREEN_TYPE} = FirstTimeFlow // return SCREEN_TYPE.NOTICE + if (forgottenPassword) { + return SCREEN_TYPE.IMPORT_SEED_PHRASE + } if (!isInitialized) { return SCREEN_TYPE.CREATE_PASSWORD } @@ -70,7 +80,13 @@ class FirstTimeFlow extends Component { renderScreen () { const {SCREEN_TYPE} = FirstTimeFlow - const {goToBuyEtherView, address} = this.props + const { + openBuyEtherModal, + address, + restoreCreatePasswordScreen, + forgottenPassword, + leaveImportSeedScreenState, + } = this.props switch (this.state.screenType) { case SCREEN_TYPE.CREATE_PASSWORD: @@ -91,8 +107,14 @@ class FirstTimeFlow extends Component { case SCREEN_TYPE.IMPORT_SEED_PHRASE: return ( <ImportSeedPhraseScreen - back={() => this.setScreenType(SCREEN_TYPE.CREATE_PASSWORD)} - next={() => this.setScreenType(SCREEN_TYPE.NOTICE)} + back={() => { + leaveImportSeedScreenState() + this.setScreenType(SCREEN_TYPE.CREATE_PASSWORD) + }} + next={() => { + const newScreenType = forgottenPassword ? null : SCREEN_TYPE.NOTICE + this.setScreenType(newScreenType) + }} /> ) case SCREEN_TYPE.UNIQUE_IMAGE: @@ -110,7 +132,7 @@ class FirstTimeFlow extends Component { case SCREEN_TYPE.BACK_UP_PHRASE: return ( <BackupPhraseScreen - next={() => goToBuyEtherView(address)} + next={() => openBuyEtherModal()} /> ) default: @@ -129,14 +151,24 @@ class FirstTimeFlow extends Component { } export default connect( - ({ metamask: { isInitialized, seedWords, noActiveNotices, selectedAddress } }) => ({ + ({ + metamask: { + isInitialized, + seedWords, + noActiveNotices, + selectedAddress, + forgottenPassword, + } + }) => ({ isInitialized, seedWords, noActiveNotices, address: selectedAddress, + forgottenPassword, }), dispatch => ({ - goToBuyEtherView: address => dispatch(onboardingBuyEthView(address)), + leaveImportSeedScreenState: () => dispatch(unMarkPasswordForgotten()), + openBuyEtherModal: () => dispatch(showModal({ name: 'DEPOSIT_ETHER'})), }) )(FirstTimeFlow) diff --git a/mascara/src/app/first-time/loading-screen.js b/mascara/src/app/first-time/loading-screen.js index 732b7f2d7..01e1c1998 100644 --- a/mascara/src/app/first-time/loading-screen.js +++ b/mascara/src/app/first-time/loading-screen.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React from 'react' +import PropTypes from 'prop-types' import Spinner from './spinner' export default function LoadingScreen({ className = '', loadingMessage }) { @@ -7,5 +8,10 @@ export default function LoadingScreen({ className = '', loadingMessage }) { <Spinner color="#1B344D" /> <div className="loading-screen__message">{loadingMessage}</div> </div> - ); + ) +} + +LoadingScreen.propTypes = { + className: PropTypes.string, + loadingMessage: PropTypes.string, } diff --git a/mascara/src/app/first-time/notice-screen.js b/mascara/src/app/first-time/notice-screen.js index be54b9fc0..caba71866 100644 --- a/mascara/src/app/first-time/notice-screen.js +++ b/mascara/src/app/first-time/notice-screen.js @@ -7,6 +7,7 @@ import { markNoticeRead } from '../../../../ui/app/actions' import Identicon from '../../../../ui/app/components/identicon' import Breadcrumbs from './breadcrumbs' import { DEFAULT_ROUTE } from '../../../../ui/app/routes' +import LoadingScreen from './loading-screen' class NoticeScreen extends Component { static propTypes = { @@ -23,6 +24,7 @@ class NoticeScreen extends Component { }), markNoticeRead: PropTypes.func, history: PropTypes.object, + isLoading: PropTypes.bool, }; static defaultProps = { @@ -60,38 +62,45 @@ class NoticeScreen extends Component { const { address, lastUnreadNotice: { title, body }, + isLoading, } = this.props const { atBottom } = this.state return ( - <div className="first-time-flow"> - <div - className="tou" - onScroll={this.onScroll} - > - <Identicon address={address} diameter={70} /> - <div className="tou__title">{title}</div> - <Markdown - className="tou__body markdown" - source={body} - skipHtml - /> - <button - className="first-time-flow__button" - onClick={atBottom && this.acceptTerms} - disabled={!atBottom} - > - Accept - </button> - <Breadcrumbs total={3} currentIndex={2} /> - </div> - </div> + isLoading + ? <LoadingScreen /> + : ( + <div className="first-view-main-wrapper"> + <div className="first-view-main"> + <div + className="tou" + onScroll={this.onScroll} + > + <Identicon address={address} diameter={70} /> + <div className="tou__title">{title}</div> + <Markdown + className="tou__body markdown" + source={body} + skipHtml + /> + <button + className="first-time-flow__button" + onClick={atBottom && this.acceptTerms} + disabled={!atBottom} + > + Accept + </button> + <Breadcrumbs total={3} currentIndex={2} /> + </div> + </div> + </div> + ) ) } } export default connect( - ({ metamask: { selectedAddress, lastUnreadNotice } }) => ({ + ({ metamask: { selectedAddress, lastUnreadNotice }, appState: { isLoading } }) => ({ lastUnreadNotice, address: selectedAddress, }), diff --git a/mascara/src/app/first-time/seed-screen.js b/mascara/src/app/first-time/seed-screen.js index dc1da851c..e88335b0c 100644 --- a/mascara/src/app/first-time/seed-screen.js +++ b/mascara/src/app/first-time/seed-screen.js @@ -74,14 +74,16 @@ class BackupPhraseScreen extends Component { {this.props.seedWords} </div> {!isShowingSecret && ( - <div className="backup-phrase__secret-blocker"> + <div + className="backup-phrase__secret-blocker" + onClick={() => this.setState({ isShowingSecret: true })} + > <LockIcon width="28px" height="35px" fill="#FFFFFF" /> - <button + <div className="backup-phrase__reveal-button" - onClick={() => this.setState({ isShowingSecret: true })} > Click here to reveal secret words - </button> + </div> </div> )} </div> @@ -94,7 +96,7 @@ class BackupPhraseScreen extends Component { return ( <div className="backup-phrase__content-wrapper"> - <div> + <div className="backup-phrase__phrase"> <div className="backup-phrase__title">Secret Backup Phrase</div> <div className="backup-phrase__body-text"> Your secret backup phrase makes it easy to back up and restore your account. @@ -124,25 +126,36 @@ class BackupPhraseScreen extends Component { Memorize this phrase. </div> </div> + <div className="backup-phrase__next-button"> + <button + className="first-time-flow__button" + onClick={() => isShowingSecret && this.setState({ + isShowingSecret: false, + page: BackupPhraseScreen.PAGE.CONFIRM, + })} + disabled={!isShowingSecret} + > + Next + </button> + <Breadcrumbs total={3} currentIndex={1} /> + </div> </div> ) } render () { - return ( - <div className="first-time-flow"> - { - this.props.isLoading - ? <LoadingScreen loadingMessage="Creating your new account" /> - : ( + return this.props.isLoading + ? <LoadingScreen loadingMessage="Creating your new account" /> + : ( + <div className="first-view-main-wrapper"> + <div className="first-view-main"> <div className="backup-phrase"> <Identicon address={this.props.address} diameter={70} /> {this.renderSecretScreen()} </div> - ) - } - </div> - ) + </div> + </div> + ) } } diff --git a/mascara/src/app/first-time/unique-image-screen.js b/mascara/src/app/first-time/unique-image-screen.js index ef6bd28ab..ede17ee3d 100644 --- a/mascara/src/app/first-time/unique-image-screen.js +++ b/mascara/src/app/first-time/unique-image-screen.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import {connect} from 'react-redux' import Identicon from '../../../../ui/app/components/identicon' import Breadcrumbs from './breadcrumbs' @@ -11,22 +12,26 @@ class UniqueImageScreen extends Component { render () { return ( - <div className="unique-image"> - <Identicon address={this.props.address} diameter={70} /> - <div className="unique-image__title">Your unique account image</div> - <div className="unique-image__body-text"> - This image was programmatically generated for you by your new account number. + <div className="first-view-main-wrapper"> + <div className="first-view-main"> + <div className="unique-image"> + <Identicon address={this.props.address} diameter={70} /> + <div className="unique-image__title">Your unique account image</div> + <div className="unique-image__body-text"> + This image was programmatically generated for you by your new account number. + </div> + <div className="unique-image__body-text"> + You’ll see this image everytime you need to confirm a transaction. + </div> + <button + className="first-time-flow__button" + onClick={this.props.next} + > + Next + </button> + <Breadcrumbs total={3} currentIndex={1} /> + </div> </div> - <div className="unique-image__body-text"> - You’ll see this image everytime you need to confirm a transaction. - </div> - <button - className="first-time-flow__button" - onClick={this.props.next} - > - Next - </button> - <Breadcrumbs total={3} currentIndex={1} /> </div> ) } diff --git a/mascara/src/app/shapeshift-form/index.js b/mascara/src/app/shapeshift-form/index.js index 15c7e95e1..53a63403a 100644 --- a/mascara/src/app/shapeshift-form/index.js +++ b/mascara/src/app/shapeshift-form/index.js @@ -1,4 +1,5 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import classnames from 'classnames' import {qrcode} from 'qrcode-npm' import {connect} from 'react-redux' |