diff options
Diffstat (limited to 'mascara')
-rw-r--r-- | mascara/src/app/buy-ether-widget/index.js | 3 | ||||
-rw-r--r-- | mascara/src/app/first-time/backup-phrase-screen.js | 7 | ||||
-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 | 32 | ||||
-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 | 170 | ||||
-rw-r--r-- | mascara/src/app/first-time/index.css | 50 | ||||
-rw-r--r-- | mascara/src/app/first-time/index.js | 43 | ||||
-rw-r--r-- | mascara/src/app/first-time/loading-screen.js | 10 | ||||
-rw-r--r-- | mascara/src/app/first-time/notice-screen.js | 72 | ||||
-rw-r--r-- | mascara/src/app/first-time/unique-image-screen.js | 3 | ||||
-rw-r--r-- | mascara/src/app/shapeshift-form/index.js | 3 |
13 files changed, 262 insertions, 142 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/backup-phrase-screen.js b/mascara/src/app/first-time/backup-phrase-screen.js index c68dacea2..9db61f3ab 100644 --- a/mascara/src/app/first-time/backup-phrase-screen.js +++ b/mascara/src/app/first-time/backup-phrase-screen.js @@ -1,5 +1,6 @@ -import React, {Component, PropTypes} from 'react' -import {connect} from 'react-redux'; +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import {connect} from 'react-redux' import classnames from 'classnames' import shuffle from 'lodash.shuffle' import {compose, onlyUpdateForPropTypes} from 'recompose' @@ -194,7 +195,7 @@ class BackupPhraseScreen extends Component { </button> </div> </div> - ) + ) } renderBack () { 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 21d29d72b..450d6a479 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -1,6 +1,7 @@ import EventEmitter from 'events' -import React, {Component, PropTypes} from 'react' -import {connect} from 'react-redux'; +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import {connect} from 'react-redux' import {createNewVaultAndKeychain} from '../../../../ui/app/actions' import LoadingScreen from './loading-screen' import Breadcrumbs from './breadcrumbs' @@ -12,12 +13,12 @@ class CreatePasswordScreen extends Component { createAccount: PropTypes.func.isRequired, goToImportWithSeedPhrase: PropTypes.func.isRequired, goToImportAccount: PropTypes.func.isRequired, - next: PropTypes.func.isRequired + next: PropTypes.func.isRequired, } state = { password: '', - confirmPassword: '' + confirmPassword: '', } constructor () { @@ -25,40 +26,39 @@ class CreatePasswordScreen extends Component { this.animationEventEmitter = new EventEmitter() } - isValid() { - const {password, confirmPassword} = this.state; + isValid () { + const {password, confirmPassword} = this.state if (!password || !confirmPassword) { - return false; + return false } if (password.length < 8) { - return false; + return false } - return password === confirmPassword; + return password === confirmPassword } createAccount = () => { if (!this.isValid()) { - return; + return } - const {password} = this.state; - const {createAccount, next} = this.props; + const {password} = this.state + const {createAccount, next} = this.props createAccount(password) - .then(next); + .then(next) } - render() { - const { isLoading, goToImportAccount, goToImportWithSeedPhrase } = this.props + render () { + const { isLoading, goToImportWithSeedPhrase } = this.props return isLoading ? <LoadingScreen loadingMessage="Creating your new account" /> : ( <div> - <h2 className="alpha-warning">Warning This is Experemental software and is a Developer BETA </h2> <div className="first-view-main"> <div className="mascara-info"> <Mascot 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 d9a9dc835..de8d675e1 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,88 +26,134 @@ 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> + const { seedPhrase, password, confirmPassword } = this.state + const { warning } = this.props + const importDisabled = warning || !seedPhrase || !password || !confirmPassword + return ( + <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})} + onChange={e => this.onChange({seedPhrase: e.target.value})} + value={this.state.seedPhrase} + placeholder="Separate each word with a single space" /> - <span - className="error" - > - {this.props.warning} - </span> + </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})} + onChange={e => this.onChange({password: e.target.value})} /> + </div> + <div className="import-account__input-wrapper"> + <label + className="import-account__input-label" + className={classnames('import-account__input-label', { + 'import-account__input-label__disabled': password.length < 8, + })} + >Confirm Password</label> <input - className="first-time-flow__input create-password__confirm-input" + className={classnames('first-time-flow__input', { + 'first-time-flow__input__disabled': password.length < 8, + })} type="password" placeholder="Confirm Password" - onChange={e => this.setState({confirmPassword: e.target.value})} + onChange={e => this.onChange({confirmPassword: e.target.value})} + disabled={password.length < 8} /> - <button - className="first-time-flow__button" - onClick={this.onClick} - > - Import - </button> </div> - ) + <button + className="first-time-flow__button" + onClick={() => !importDisabled && this.onClick()} + disabled={importDisabled} + > + Import + </button> + </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 f91c72f0e..f59eb4ce1 100644 --- a/mascara/src/app/first-time/index.css +++ b/mascara/src/app/first-time/index.css @@ -1,16 +1,18 @@ .first-time-flow { - height: 100vh; width: 100vw; - background-color: #FFF; + background-color: #fff; overflow: auto; + display: flex; + justify-content: center; + flex: 1 0 auto; } .alpha-warning { background: #f7861c; color: #fff; line-height: 2em; - padding-left: 2em; + padding-left: 10vw; } .first-view-main { @@ -23,7 +25,6 @@ display: flex; flex-flow: column; margin-top: 70px; - margin-right: 10vw; width: 35vw; max-width: 550px; } @@ -44,10 +45,18 @@ .buy-ether { display: flex; flex-flow: column nowrap; - margin: 67px 0 0 146px; + margin: 67px 0 50px; max-width: 35rem; } +.create-password { + margin: 67px 0 50px; +} + +.import-account { + max-width: initial; +} + @media only screen and (max-width: 575px) { .create-password, .unique-image, @@ -135,14 +144,16 @@ .backup-phrase__title, .import-account__title, .buy-ether__title { - width: 280px; color: #1B344D; font-size: 40px; - font-weight: 500; line-height: 51px; margin-bottom: 24px; } +.import-account__title { + margin-bottom: 10px; +} + .tou__title, .backup-phrase__title { width: 480px; @@ -288,9 +299,7 @@ .import-account__back-button:hover { margin-bottom: 18px; color: #22232C; - font-family: Montserrat Regular; font-size: 16px; - font-weight: 500; line-height: 21px; } @@ -311,6 +320,12 @@ button.backup-phrase__reveal-button:hover { .import-account__secret-phrase { font-size: 16px; + margin: initial; +} + +.import-account__secret-phrase::placeholder { + color: #9B9B9B; + font-weight: 200; } .backup-phrase__confirm-seed-options { @@ -350,9 +365,7 @@ button.backup-phrase__confirm-seed-option:hover { .import-account__selector-label { color: #1B344D; - font-family: Montserrat Light; - font-size: 18px; - line-height: 23px; + font-size: 16px; } .import-account__dropdown { @@ -394,7 +407,6 @@ button.backup-phrase__confirm-seed-option:hover { margin-top: 10px; width: 422px; color: #FF001F; - font-family: Montserrat Light; font-size: 16px; line-height: 21px; } @@ -402,10 +414,12 @@ button.backup-phrase__confirm-seed-option:hover { .import-account__input-label { margin-bottom: 9px; color: #1B344D; - font-family: Montserrat Light; font-size: 18px; line-height: 23px; - text-transform: uppercase; +} + +.import-account__input-label__disabled { + opacity: 0.5; } .import-account__input { @@ -549,11 +563,15 @@ button.backup-phrase__confirm-seed-option:hover { width: 350px; font-size: 18px; line-height: 24px; - padding: 15px 28px; + padding: 15px; border: 1px solid #CDCDCD; background-color: #FFFFFF; } +.first-time-flow__input__disabled { + opacity: 0.5; +} + .first-time-flow__input::placeholder { color: #9B9B9B; font-weight: 200; diff --git a/mascara/src/app/first-time/index.js b/mascara/src/app/first-time/index.js index 66b591bd8..da2f6bab9 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,10 @@ import NoticeScreen from './notice-screen' import BackupPhraseScreen from './backup-phrase-screen' import ImportAccountScreen from './import-account-screen' import ImportSeedPhraseScreen from './import-seed-phrase-screen' -import {onboardingBuyEthView} from '../../../../ui/app/actions' +import { + onboardingBuyEthView, + unMarkPasswordForgotten, +} from '../../../../ui/app/actions' class FirstTimeFlow extends Component { @@ -32,6 +36,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 +55,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 +79,13 @@ class FirstTimeFlow extends Component { renderScreen () { const {SCREEN_TYPE} = FirstTimeFlow - const {goToBuyEtherView, address} = this.props + const { + goToBuyEtherView, + address, + restoreCreatePasswordScreen, + forgottenPassword, + leaveImportSeedScreenState, + } = this.props switch (this.state.screenType) { case SCREEN_TYPE.CREATE_PASSWORD: @@ -91,8 +106,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: @@ -129,13 +150,23 @@ 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 => ({ + leaveImportSeedScreenState: () => dispatch(unMarkPasswordForgotten()), goToBuyEtherView: address => dispatch(onboardingBuyEthView(address)), }) )(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 d09070a95..0f0a7e95d 100644 --- a/mascara/src/app/first-time/notice-screen.js +++ b/mascara/src/app/first-time/notice-screen.js @@ -1,10 +1,12 @@ -import React, {Component, PropTypes} from 'react' +import React, { Component } from 'react' +import PropTypes from 'prop-types' import Markdown from 'react-markdown' import {connect} from 'react-redux' import debounce from 'lodash.debounce' import {markNoticeRead} from '../../../../ui/app/actions' import Identicon from '../../../../ui/app/components/identicon' import Breadcrumbs from './breadcrumbs' +import LoadingScreen from './loading-screen' class NoticeScreen extends Component { static propTypes = { @@ -12,25 +14,26 @@ class NoticeScreen extends Component { lastUnreadNotice: PropTypes.shape({ title: PropTypes.string, date: PropTypes.string, - body: PropTypes.string + body: PropTypes.string, }), - next: PropTypes.func.isRequired + next: PropTypes.func.isRequired, + markNoticeRead: PropTypes.func, }; static defaultProps = { - lastUnreadNotice: {} + lastUnreadNotice: {}, }; state = { atBottom: false, } - componentDidMount() { + componentDidMount () { this.onScroll() } acceptTerms = () => { - const { markNoticeRead, lastUnreadNotice, next } = this.props; + const { markNoticeRead, lastUnreadNotice, next } = this.props const defer = markNoticeRead(lastUnreadNotice) .then(() => this.setState({ atBottom: false })) @@ -43,50 +46,53 @@ class NoticeScreen extends Component { if (this.state.atBottom) return const target = document.querySelector('.tou__body') - const {scrollTop, offsetHeight, scrollHeight} = target; - const atBottom = scrollTop + offsetHeight >= scrollHeight; + const {scrollTop, offsetHeight, scrollHeight} = target + const atBottom = scrollTop + offsetHeight >= scrollHeight this.setState({atBottom: atBottom}) }, 25) - render() { + render () { const { address, - lastUnreadNotice: { title, body } - } = this.props; + lastUnreadNotice: { title, body }, + isLoading, + } = this.props const { atBottom } = this.state return ( - <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} + isLoading + ? <LoadingScreen /> + : <div + className="tou" + onScroll={this.onScroll} > - Accept - </button> - <Breadcrumbs total={3} currentIndex={2} /> - </div> + <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> ) } } export default connect( - ({ metamask: { selectedAddress, lastUnreadNotice } }) => ({ + ({ metamask: { selectedAddress, lastUnreadNotice }, appState: { isLoading } }) => ({ lastUnreadNotice, - address: selectedAddress + address: selectedAddress, }), dispatch => ({ - markNoticeRead: notice => dispatch(markNoticeRead(notice)) + markNoticeRead: notice => dispatch(markNoticeRead(notice)), }) )(NoticeScreen) diff --git a/mascara/src/app/first-time/unique-image-screen.js b/mascara/src/app/first-time/unique-image-screen.js index ef6bd28ab..46448aacf 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' 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' |