From 6277a4c46aa2fd94f0fff047aff346d7f255224d Mon Sep 17 00:00:00 2001 From: Alexander Tseung Date: Mon, 2 Apr 2018 02:59:49 -0700 Subject: Refactor onboarding flow --- mascara/src/app/first-time/confirm-seed-screen.js | 129 ++++++----- .../src/app/first-time/create-password-screen.js | 254 ++++++++++++++------- .../app/first-time/import-seed-phrase-screen.js | 4 +- mascara/src/app/first-time/index.js | 54 +++-- mascara/src/app/first-time/notice-screen.js | 52 ++++- mascara/src/app/first-time/seed-screen.js | 20 +- mascara/src/app/first-time/unique-image-screen.js | 18 +- 7 files changed, 343 insertions(+), 188 deletions(-) (limited to 'mascara/src/app/first-time') diff --git a/mascara/src/app/first-time/confirm-seed-screen.js b/mascara/src/app/first-time/confirm-seed-screen.js index c9382689e..6eabd7544 100644 --- a/mascara/src/app/first-time/confirm-seed-screen.js +++ b/mascara/src/app/first-time/confirm-seed-screen.js @@ -1,14 +1,15 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' +import { withRouter } from 'react-router-dom' import classnames from 'classnames' import shuffle from 'lodash.shuffle' -import { compose, onlyUpdateForPropTypes } from 'recompose' +import { compose } from 'recompose' import Identicon from '../../../../ui/app/components/identicon' import { confirmSeedWords } from '../../../../ui/app/actions' import Breadcrumbs from './breadcrumbs' import LoadingScreen from './loading-screen' -import { DEFAULT_ROUTE } from '../../../../ui/app/routes' +import { INITIALIZE_ROUTE, DEFAULT_ROUTE } from '../../../../ui/app/routes' class ConfirmSeedScreen extends Component { static propTypes = { @@ -35,10 +36,18 @@ class ConfirmSeedScreen extends Component { componentWillMount () { const { seedWords, history } = this.props if (!seedWords) { - history.push(DEFAULT_ROUTE) + history.push(INITIALIZE_ROUTE) } } + handleClick () { + this.props.confirmSeedWords() + .then(() => { + console.log('FINISHED') + this.props.history.push(DEFAULT_ROUTE) + }) + } + render () { const { seedWords, confirmSeedWords, history } = this.props const { selectedSeeds, shuffledSeeds } = this.state @@ -50,66 +59,70 @@ class ConfirmSeedScreen extends Component { this.props.isLoading ? : ( -
- -
-
-
- Confirm your Secret Backup Phrase -
-
- Please select each phrase in order to make sure it is correct. -
-
- {selectedSeeds.map(([_, word], i) => ( +
+
+
+ +
+
+
+ Confirm your Secret Backup Phrase +
+
+ Please select each phrase in order to make sure it is correct. +
+
+ {selectedSeeds.map(([_, word], i) => ( + + ))} +
+
+ {shuffledSeeds.map((word, i) => { + const isSelected = selectedSeeds + .filter(([index, seed]) => seed === word && index === i) + .length + + return ( + + ) + })} +
- ))} -
-
- {shuffledSeeds.map((word, i) => { - const isSelected = selectedSeeds - .filter(([index, seed]) => seed === word && index === i) - .length - - return ( - - ) - })} +
- +
-
) } @@ -119,7 +132,7 @@ class ConfirmSeedScreen extends Component { } export default compose( - onlyUpdateForPropTypes, + withRouter, connect( ({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({ seedWords, diff --git a/mascara/src/app/first-time/create-password-screen.js b/mascara/src/app/first-time/create-password-screen.js index c34391fa6..7b8971afe 100644 --- a/mascara/src/app/first-time/create-password-screen.js +++ b/mascara/src/app/first-time/create-password-screen.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import {connect} from 'react-redux' -import { withRouter } from 'react-router-dom' +import { withRouter, Redirect } from 'react-router-dom' import { compose } from 'recompose' import { createNewVaultAndKeychain } from '../../../../ui/app/actions' import LoadingScreen from './loading-screen' @@ -11,8 +11,10 @@ import Mascot from '../../../../ui/app/components/mascot' import classnames from 'classnames' import { DEFAULT_ROUTE, + INITIALIZE_UNIQUE_IMAGE_ROUTE, INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, - INITIALIZE_IMPORT_ACCOUNT_ROUTE, + // INITIALIZE_IMPORT_ACCOUNT_ROUTE, + INITIALIZE_NOTICE_ROUTE, } from '../../../../ui/app/routes' class CreatePasswordScreen extends Component { @@ -28,6 +30,7 @@ class CreatePasswordScreen extends Component { state = { password: '', confirmPassword: '', + isLoading: false, } constructor () { @@ -36,9 +39,11 @@ class CreatePasswordScreen extends Component { } componentWillMount () { - const { isInitialized, isUnlocked, history } = this.props - if (isInitialized || isUnlocked) { - history.push(DEFAULT_ROUTE) + const { isInitialized, isUnlocked, history, noActiveNotices } = this.props + + if (isInitialized) { + console.log('%c IM already initialized', 'background: #222; color: #bada55') + history.push(INITIALIZE_NOTICE_ROUTE) } } @@ -64,95 +69,188 @@ class CreatePasswordScreen extends Component { const { password } = this.state const { createAccount, history } = this.props + this.setState({ isLoading: true }) createAccount(password) - .then(() => history.push(DEFAULT_ROUTE)) + .then(() => { + // this.setState({ isLoading: false }) + history.push(INITIALIZE_UNIQUE_IMAGE_ROUTE) + }) + .catch(() => this.setState({ isLoading: false})) + } + + renderFields () { + const { isMascara, history } = this.props + const { isLoading } = this.state + + return ( +
+
+ {isMascara &&
+ +
+ MetaMask is a secure identity vault for Ethereum. +
+
+ It allows you to hold ether & tokens, and interact with decentralized applications. +
+
} +
+
+ Create Password +
+ this.setState({password: e.target.value})} + /> + this.setState({confirmPassword: e.target.value})} + /> + + { + e.preventDefault() + history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE) + }} + > + Import with seed phrase + + { /* } + { + e.preventDefault() + history.push(INITIALIZE_IMPORT_ACCOUNT_ROUTE) + }} + > + Import an account + + { */ } + +
+
+
+ ) } render () { - const { isLoading, isMascara, history } = this.props - - return isLoading - ? - : ( -
-
- {isMascara &&
- -
- MetaMask is a secure identity vault for Ethereum. -
-
- It allows you to hold ether & tokens, and interact with decentralized applications. -
-
} -
-
- Create Password -
- this.setState({password: e.target.value})} - /> - this.setState({confirmPassword: e.target.value})} - /> - - { - e.preventDefault() - history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE) - }} - > - Import with seed phrase - - { /* } - { - e.preventDefault() - history.push(INITIALIZE_IMPORT_ACCOUNT_ROUTE) - }} - > - Import an account - - { */ } - + const { isInitialized, isUnlocked, history, noActiveNotices, isMascara } = this.props + + // if (isInitialized) { + // console.log('%c IM already initialized', 'background: #222; color: #bada55') + // if (!noActiveNotices) { + // console.log('%c GOING TO NOTICES', 'background: #222; color: #bada55') + // // history.replace(INITIALIZE_NOTICE_ROUTE) + // return + // } else { + // console.log('%c GOING TO DEFAULT', 'background: #222; color: #bada55') + // // history.replace(DEFAULT_ROUTE) + // return + // } + // } + + return ( +
+
+ {isMascara &&
+ +
+ MetaMask is a secure identity vault for Ethereum. +
+
+ It allows you to hold ether & tokens, and interact with decentralized applications. +
+
} +
+
+ Create Password
+ this.setState({password: e.target.value})} + /> + this.setState({confirmPassword: e.target.value})} + /> + + { + e.preventDefault() + history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE) + }} + > + Import with seed phrase + + { /* } + { + e.preventDefault() + history.push(INITIALIZE_IMPORT_ACCOUNT_ROUTE) + }} + > + Import an account + + { */ } +
- ) +
+ ) } } -const mapStateToProps = state => { - const { metamask: { isInitialized, isUnlocked, isMascara }, appState: { isLoading } } = state +const mapStateToProps = ({ metamask, appState }) => { + const { isInitialized, isUnlocked, isMascara, noActiveNotices } = metamask + const { isLoading } = appState return { isLoading, isInitialized, isUnlocked, isMascara, + noActiveNotices, } } 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 4eec37723..5c2b21b0a 100644 --- a/mascara/src/app/first-time/import-seed-phrase-screen.js +++ b/mascara/src/app/first-time/import-seed-phrase-screen.js @@ -8,7 +8,7 @@ import { displayWarning, unMarkPasswordForgotten, } from '../../../../ui/app/actions' -import { DEFAULT_ROUTE } from '../../../../ui/app/routes' +import { DEFAULT_ROUTE, INITIALIZE_NOTICE_ROUTE } from '../../../../ui/app/routes' class ImportSeedPhraseScreen extends Component { static propTypes = { @@ -71,7 +71,7 @@ class ImportSeedPhraseScreen extends Component { leaveImportSeedScreenState() createNewVaultAndRestore(password, this.parseSeedPhrase(seedPhrase)) - .then(() => history.push(DEFAULT_ROUTE)) + .then(() => history.push(INITIALIZE_NOTICE_ROUTE)) } render () { diff --git a/mascara/src/app/first-time/index.js b/mascara/src/app/first-time/index.js index ea56a2f6e..5f47145a3 100644 --- a/mascara/src/app/first-time/index.js +++ b/mascara/src/app/first-time/index.js @@ -9,6 +9,7 @@ import NoticeScreen from './notice-screen' import BackupPhraseScreen from './seed-screen' import ImportAccountScreen from './import-account-screen' import ImportSeedPhraseScreen from './import-seed-phrase-screen' +import ConfirmSeed from './confirm-seed-screen' import { onboardingBuyEthView, unMarkPasswordForgotten, @@ -19,8 +20,14 @@ import { WELCOME_ROUTE, INITIALIZE_ROUTE, INITIALIZE_IMPORT_ACCOUNT_ROUTE, + INITIALIZE_UNIQUE_IMAGE_ROUTE, INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, + INITIALIZE_NOTICE_ROUTE, + INITIALIZE_BACKUP_PHRASE_ROUTE, + INITIALIZE_CONFIRM_SEED_ROUTE, + INITIALIZE_CREATE_PASSWORD_ROUTE, } from '../../../../ui/app/routes' +import WelcomeScreen from '../../../../ui/app/welcome-screen' class FirstTimeFlow extends Component { @@ -60,11 +67,17 @@ class FirstTimeFlow extends Component { } componentDidMount () { - const { isInitialized, isUnlocked, history } = this.props + const { isInitialized, isUnlocked, history, noActiveNotices } = this.props + + // if (isInitialized || isUnlocked) { + // history.push(DEFAULT_ROUTE) + // } + + // if (!noActiveNotices) { + // console.log('INITIALIZE ACTIVE NOTICES') + // history.push(INITIALIZE_NOTICE_ROUTE) + // } - if (isInitialized || isUnlocked) { - history.push(DEFAULT_ROUTE) - } } setScreenType (screenType) { @@ -161,21 +174,24 @@ class FirstTimeFlow extends Component { } render () { - return this.props.welcomeScreenSeen - ? ( -
- - - - - -
- ) - : + return ( +
+ + + + + + + + + + +
+ ) } } diff --git a/mascara/src/app/first-time/notice-screen.js b/mascara/src/app/first-time/notice-screen.js index a342f059c..6d45f4353 100644 --- a/mascara/src/app/first-time/notice-screen.js +++ b/mascara/src/app/first-time/notice-screen.js @@ -2,11 +2,17 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import Markdown from 'react-markdown' import { connect } from 'react-redux' +import { withRouter } from 'react-router-dom' +import { compose } from 'recompose' import debounce from 'lodash.debounce' 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 { + INITIALIZE_ROUTE, + DEFAULT_ROUTE, + INITIALIZE_BACKUP_PHRASE_ROUTE, +} from '../../../../ui/app/routes' import LoadingScreen from './loading-screen' class NoticeScreen extends Component { @@ -25,6 +31,7 @@ class NoticeScreen extends Component { markNoticeRead: PropTypes.func, history: PropTypes.object, isLoading: PropTypes.bool, + noActiveNotices: PropTypes.bool, }; static defaultProps = { @@ -35,14 +42,27 @@ class NoticeScreen extends Component { atBottom: false, } - componentDidMount () { + componentWillMount () { + if (this.props.noActiveNotices) { + console.log('%c NOTICESCREEN NOACTIVENOTICES', 'background: #222; color: #bada55') + this.props.history.push(INITIALIZE_BACKUP_PHRASE_ROUTE) + } + this.onScroll() } acceptTerms = () => { const { markNoticeRead, lastUnreadNotice, history } = this.props markNoticeRead(lastUnreadNotice) - .then(() => history.push(DEFAULT_ROUTE)) + .then(hasActiveNotices => { + console.log('ACCEPT TERMS, NO ACTIVE NOTICES', hasActiveNotices, 'background: #222; color: #bada55') + if (!hasActiveNotices) { + history.push(INITIALIZE_BACKUP_PHRASE_ROUTE) + } else { + this.setState({ atBottom: false }) + this.onScroll() + } + }) } onScroll = debounce(() => { @@ -98,12 +118,24 @@ class NoticeScreen extends Component { } } -export default connect( - ({ metamask: { selectedAddress, lastUnreadNotice }, appState: { isLoading } }) => ({ - lastUnreadNotice, +const mapStateToProps = ({ metamask, appState }) => { + const { selectedAddress, lastUnreadNotice, noActiveNotices } = metamask + const { isLoading } = appState + + return { address: selectedAddress, - }), - dispatch => ({ - markNoticeRead: notice => dispatch(markNoticeRead(notice)), - }) + lastUnreadNotice, + noActiveNotices, + isLoading, + } +} + +export default compose( + withRouter, + connect( + mapStateToProps, + dispatch => ({ + markNoticeRead: notice => dispatch(markNoticeRead(notice)), + }) + ) )(NoticeScreen) diff --git a/mascara/src/app/first-time/seed-screen.js b/mascara/src/app/first-time/seed-screen.js index e88335b0c..1ff4f8ab3 100644 --- a/mascara/src/app/first-time/seed-screen.js +++ b/mascara/src/app/first-time/seed-screen.js @@ -2,11 +2,12 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import classnames from 'classnames' -import { compose, onlyUpdateForPropTypes } from 'recompose' +import { withRouter } from 'react-router-dom' +import { compose } from 'recompose' import Identicon from '../../../../ui/app/components/identicon' import Breadcrumbs from './breadcrumbs' import LoadingScreen from './loading-screen' -import { DEFAULT_ROUTE, CONFIRM_SEED_ROUTE } from '../../../../ui/app/routes' +import { DEFAULT_ROUTE, INITIALIZE_CONFIRM_SEED_ROUTE } from '../../../../ui/app/routes' const LockIcon = props => ( {this.renderSecretWordsContainer()} - -
Tips:
@@ -129,10 +122,7 @@ class BackupPhraseScreen extends Component {
@@ -37,8 +40,11 @@ class UniqueImageScreen extends Component { } } -export default connect( - ({ metamask: { selectedAddress } }) => ({ - address: selectedAddress, - }) +export default compose( + withRouter, + connect( + ({ metamask: { selectedAddress } }) => ({ + address: selectedAddress, + }) + ) )(UniqueImageScreen) -- cgit