Refactor onboarding flow

feature/default_network_editable
Alexander Tseung 7 years ago
parent 2fa554a641
commit 6277a4c46a
  1. 129
      mascara/src/app/first-time/confirm-seed-screen.js
  2. 254
      mascara/src/app/first-time/create-password-screen.js
  3. 4
      mascara/src/app/first-time/import-seed-phrase-screen.js
  4. 54
      mascara/src/app/first-time/index.js
  5. 52
      mascara/src/app/first-time/notice-screen.js
  6. 20
      mascara/src/app/first-time/seed-screen.js
  7. 18
      mascara/src/app/first-time/unique-image-screen.js
  8. 5
      ui/app/actions.js
  9. 24
      ui/app/app.js
  10. 4
      ui/app/components/pages/add-token.js
  11. 22
      ui/app/components/pages/home.js
  12. 2
      ui/app/components/pages/keychains/restore-vault.js
  13. 2
      ui/app/components/pages/keychains/reveal-seed.js
  14. 8
      ui/app/routes.js
  15. 6
      ui/app/send-v2.js
  16. 34
      ui/app/welcome-screen.js

@ -1,14 +1,15 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import classnames from 'classnames' import classnames from 'classnames'
import shuffle from 'lodash.shuffle' import shuffle from 'lodash.shuffle'
import { compose, onlyUpdateForPropTypes } from 'recompose' import { compose } from 'recompose'
import Identicon from '../../../../ui/app/components/identicon' import Identicon from '../../../../ui/app/components/identicon'
import { confirmSeedWords } from '../../../../ui/app/actions' import { confirmSeedWords } from '../../../../ui/app/actions'
import Breadcrumbs from './breadcrumbs' import Breadcrumbs from './breadcrumbs'
import LoadingScreen from './loading-screen' 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 { class ConfirmSeedScreen extends Component {
static propTypes = { static propTypes = {
@ -35,10 +36,18 @@ class ConfirmSeedScreen extends Component {
componentWillMount () { componentWillMount () {
const { seedWords, history } = this.props const { seedWords, history } = this.props
if (!seedWords) { 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 () { render () {
const { seedWords, confirmSeedWords, history } = this.props const { seedWords, confirmSeedWords, history } = this.props
const { selectedSeeds, shuffledSeeds } = this.state const { selectedSeeds, shuffledSeeds } = this.state
@ -50,66 +59,70 @@ class ConfirmSeedScreen extends Component {
this.props.isLoading this.props.isLoading
? <LoadingScreen loadingMessage="Creating your new account" /> ? <LoadingScreen loadingMessage="Creating your new account" />
: ( : (
<div className="backup-phrase"> <div className="first-view-main-wrapper">
<Identicon address={this.props.address} diameter={70} /> <div className="first-view-main">
<div className="backup-phrase__content-wrapper"> <div className="backup-phrase">
<div> <Identicon address={this.props.address} diameter={70} />
<div className="backup-phrase__title"> <div className="backup-phrase__content-wrapper">
Confirm your Secret Backup Phrase <div>
</div> <div className="backup-phrase__title">
<div className="backup-phrase__body-text"> Confirm your Secret Backup Phrase
Please select each phrase in order to make sure it is correct. </div>
</div> <div className="backup-phrase__body-text">
<div className="backup-phrase__confirm-secret"> Please select each phrase in order to make sure it is correct.
{selectedSeeds.map(([_, word], i) => ( </div>
<div className="backup-phrase__confirm-secret">
{selectedSeeds.map(([_, word], i) => (
<button
key={i}
className="backup-phrase__confirm-seed-option"
>
{word}
</button>
))}
</div>
<div className="backup-phrase__confirm-seed-options">
{shuffledSeeds.map((word, i) => {
const isSelected = selectedSeeds
.filter(([index, seed]) => seed === word && index === i)
.length
return (
<button
key={i}
className={classnames('backup-phrase__confirm-seed-option', {
'backup-phrase__confirm-seed-option--selected': isSelected,
})}
onClick={() => {
if (!isSelected) {
this.setState({
selectedSeeds: [...selectedSeeds, [i, word]],
})
} else {
this.setState({
selectedSeeds: selectedSeeds
.filter(([index, seed]) => !(seed === word && index === i)),
})
}
}}
>
{word}
</button>
)
})}
</div>
<button <button
key={i} className="first-time-flow__button"
className="backup-phrase__confirm-seed-option" onClick={() => isValid && this.handleClick()}
disabled={!isValid}
> >
{word} Confirm
</button> </button>
))} </div>
</div>
<div className="backup-phrase__confirm-seed-options">
{shuffledSeeds.map((word, i) => {
const isSelected = selectedSeeds
.filter(([index, seed]) => seed === word && index === i)
.length
return (
<button
key={i}
className={classnames('backup-phrase__confirm-seed-option', {
'backup-phrase__confirm-seed-option--selected': isSelected,
})}
onClick={() => {
if (!isSelected) {
this.setState({
selectedSeeds: [...selectedSeeds, [i, word]],
})
} else {
this.setState({
selectedSeeds: selectedSeeds
.filter(([index, seed]) => !(seed === word && index === i)),
})
}
}}
>
{word}
</button>
)
})}
</div> </div>
<button <Breadcrumbs total={3} currentIndex={1} />
className="first-time-flow__button"
onClick={() => isValid && confirmSeedWords().then(() => history.push(DEFAULT_ROUTE))}
disabled={!isValid}
>
Confirm
</button>
</div> </div>
</div> </div>
<Breadcrumbs total={3} currentIndex={1} />
</div> </div>
) )
} }
@ -119,7 +132,7 @@ class ConfirmSeedScreen extends Component {
} }
export default compose( export default compose(
onlyUpdateForPropTypes, withRouter,
connect( connect(
({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({ ({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({
seedWords, seedWords,

@ -1,7 +1,7 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import {connect} from 'react-redux' import {connect} from 'react-redux'
import { withRouter } from 'react-router-dom' import { withRouter, Redirect } from 'react-router-dom'
import { compose } from 'recompose' import { compose } from 'recompose'
import { createNewVaultAndKeychain } from '../../../../ui/app/actions' import { createNewVaultAndKeychain } from '../../../../ui/app/actions'
import LoadingScreen from './loading-screen' import LoadingScreen from './loading-screen'
@ -11,8 +11,10 @@ import Mascot from '../../../../ui/app/components/mascot'
import classnames from 'classnames' import classnames from 'classnames'
import { import {
DEFAULT_ROUTE, DEFAULT_ROUTE,
INITIALIZE_UNIQUE_IMAGE_ROUTE,
INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
INITIALIZE_IMPORT_ACCOUNT_ROUTE, // INITIALIZE_IMPORT_ACCOUNT_ROUTE,
INITIALIZE_NOTICE_ROUTE,
} from '../../../../ui/app/routes' } from '../../../../ui/app/routes'
class CreatePasswordScreen extends Component { class CreatePasswordScreen extends Component {
@ -28,6 +30,7 @@ class CreatePasswordScreen extends Component {
state = { state = {
password: '', password: '',
confirmPassword: '', confirmPassword: '',
isLoading: false,
} }
constructor () { constructor () {
@ -36,9 +39,11 @@ class CreatePasswordScreen extends Component {
} }
componentWillMount () { componentWillMount () {
const { isInitialized, isUnlocked, history } = this.props const { isInitialized, isUnlocked, history, noActiveNotices } = this.props
if (isInitialized || isUnlocked) {
history.push(DEFAULT_ROUTE) 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 { password } = this.state
const { createAccount, history } = this.props const { createAccount, history } = this.props
this.setState({ isLoading: true })
createAccount(password) 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 (
<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"
height="225"
/>
<div className="info">
MetaMask is a secure identity vault for Ethereum.
</div>
<div className="info">
It allows you to hold ether & tokens, and interact with decentralized applications.
</div>
</div>}
<div className="create-password">
<div className="create-password__title">
Create Password
</div>
<input
className="first-time-flow__input"
type="password"
placeholder="New Password (min 8 characters)"
onChange={e => this.setState({password: e.target.value})}
/>
<input
className="first-time-flow__input create-password__confirm-input"
type="password"
placeholder="Confirm Password"
onChange={e => this.setState({confirmPassword: e.target.value})}
/>
<button
className="first-time-flow__button"
disabled={!this.isValid()}
onClick={this.createAccount}
>
Create
</button>
<a
href=""
className="first-time-flow__link create-password__import-link"
onClick={e => {
e.preventDefault()
history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE)
}}
>
Import with seed phrase
</a>
{ /* }
<a
href=""
className="first-time-flow__link create-password__import-link"
onClick={e => {
e.preventDefault()
history.push(INITIALIZE_IMPORT_ACCOUNT_ROUTE)
}}
>
Import an account
</a>
{ */ }
<Breadcrumbs total={3} currentIndex={0} />
</div>
</div>
</div>
)
} }
render () { render () {
const { isLoading, isMascara, history } = this.props const { isInitialized, isUnlocked, history, noActiveNotices, isMascara } = this.props
return isLoading // if (isInitialized) {
? <LoadingScreen loadingMessage="Creating your new account" /> // console.log('%c IM already initialized', 'background: #222; color: #bada55')
: ( // if (!noActiveNotices) {
<div className={classnames({ 'first-view-main-wrapper': !isMascara })}> // console.log('%c GOING TO NOTICES', 'background: #222; color: #bada55')
<div className={classnames({ // // history.replace(INITIALIZE_NOTICE_ROUTE)
'first-view-main': !isMascara, // return <Redirect to={INITIALIZE_NOTICE_ROUTE} />
'first-view-main__mascara': isMascara, // } else {
})}> // console.log('%c GOING TO DEFAULT', 'background: #222; color: #bada55')
{isMascara && <div className="mascara-info first-view-phone-invisible"> // // history.replace(DEFAULT_ROUTE)
<Mascot // return <Redirect to={DEFAULT_ROUTE} />
animationEventEmitter={this.animationEventEmitter} // }
width="225" // }
height="225"
/> return (
<div className="info"> <div className={classnames({ 'first-view-main-wrapper': !isMascara })}>
MetaMask is a secure identity vault for Ethereum. <div className={classnames({
</div> 'first-view-main': !isMascara,
<div className="info"> 'first-view-main__mascara': isMascara,
It allows you to hold ether & tokens, and interact with decentralized applications. })}>
</div> {isMascara && <div className="mascara-info first-view-phone-invisible">
</div>} <Mascot
<div className="create-password"> animationEventEmitter={this.animationEventEmitter}
<div className="create-password__title"> width="225"
Create Password height="225"
</div> />
<input <div className="info">
className="first-time-flow__input" MetaMask is a secure identity vault for Ethereum.
type="password" </div>
placeholder="New Password (min 8 characters)" <div className="info">
onChange={e => this.setState({password: e.target.value})} It allows you to hold ether & tokens, and interact with decentralized applications.
/> </div>
<input </div>}
className="first-time-flow__input create-password__confirm-input" <div className="create-password">
type="password" <div className="create-password__title">
placeholder="Confirm Password" Create Password
onChange={e => this.setState({confirmPassword: e.target.value})}
/>
<button
className="first-time-flow__button"
disabled={!this.isValid()}
onClick={this.createAccount}
>
Create
</button>
<a
href=""
className="first-time-flow__link create-password__import-link"
onClick={e => {
e.preventDefault()
history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE)
}}
>
Import with seed phrase
</a>
{ /* }
<a
href=""
className="first-time-flow__link create-password__import-link"
onClick={e => {
e.preventDefault()
history.push(INITIALIZE_IMPORT_ACCOUNT_ROUTE)
}}
>
Import an account
</a>
{ */ }
<Breadcrumbs total={3} currentIndex={0} />
</div> </div>
<input
className="first-time-flow__input"
type="password"
placeholder="New Password (min 8 characters)"
onChange={e => this.setState({password: e.target.value})}
/>
<input
className="first-time-flow__input create-password__confirm-input"
type="password"
placeholder="Confirm Password"
onChange={e => this.setState({confirmPassword: e.target.value})}
/>
<button
className="first-time-flow__button"
disabled={!this.isValid()}
onClick={this.createAccount}
>
Create
</button>
<a
href=""
className="first-time-flow__link create-password__import-link"
onClick={e => {
e.preventDefault()
history.push(INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE)
}}
>
Import with seed phrase
</a>
{ /* }
<a
href=""
className="first-time-flow__link create-password__import-link"
onClick={e => {
e.preventDefault()
history.push(INITIALIZE_IMPORT_ACCOUNT_ROUTE)
}}
>
Import an account
</a>
{ */ }
<Breadcrumbs total={3} currentIndex={0} />
</div> </div>
</div> </div>
) </div>
)
} }
} }
const mapStateToProps = state => { const mapStateToProps = ({ metamask, appState }) => {
const { metamask: { isInitialized, isUnlocked, isMascara }, appState: { isLoading } } = state const { isInitialized, isUnlocked, isMascara, noActiveNotices } = metamask
const { isLoading } = appState
return { return {
isLoading, isLoading,
isInitialized, isInitialized,
isUnlocked, isUnlocked,
isMascara, isMascara,
noActiveNotices,
} }
} }

@ -8,7 +8,7 @@ import {
displayWarning, displayWarning,
unMarkPasswordForgotten, unMarkPasswordForgotten,
} from '../../../../ui/app/actions' } 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 { class ImportSeedPhraseScreen extends Component {
static propTypes = { static propTypes = {
@ -71,7 +71,7 @@ class ImportSeedPhraseScreen extends Component {
leaveImportSeedScreenState() leaveImportSeedScreenState()
createNewVaultAndRestore(password, this.parseSeedPhrase(seedPhrase)) createNewVaultAndRestore(password, this.parseSeedPhrase(seedPhrase))
.then(() => history.push(DEFAULT_ROUTE)) .then(() => history.push(INITIALIZE_NOTICE_ROUTE))
} }
render () { render () {

@ -9,6 +9,7 @@ import NoticeScreen from './notice-screen'
import BackupPhraseScreen from './seed-screen' import BackupPhraseScreen from './seed-screen'
import ImportAccountScreen from './import-account-screen' import ImportAccountScreen from './import-account-screen'
import ImportSeedPhraseScreen from './import-seed-phrase-screen' import ImportSeedPhraseScreen from './import-seed-phrase-screen'
import ConfirmSeed from './confirm-seed-screen'
import { import {
onboardingBuyEthView, onboardingBuyEthView,
unMarkPasswordForgotten, unMarkPasswordForgotten,
@ -19,8 +20,14 @@ import {
WELCOME_ROUTE, WELCOME_ROUTE,
INITIALIZE_ROUTE, INITIALIZE_ROUTE,
INITIALIZE_IMPORT_ACCOUNT_ROUTE, INITIALIZE_IMPORT_ACCOUNT_ROUTE,
INITIALIZE_UNIQUE_IMAGE_ROUTE,
INITIALIZE_IMPORT_WITH_SEED_PHRASE_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' } from '../../../../ui/app/routes'
import WelcomeScreen from '../../../../ui/app/welcome-screen'
class FirstTimeFlow extends Component { class FirstTimeFlow extends Component {
@ -60,11 +67,17 @@ class FirstTimeFlow extends Component {
} }
componentDidMount () { 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) { setScreenType (screenType) {
@ -161,21 +174,24 @@ class FirstTimeFlow extends Component {
} }
render () { render () {
return this.props.welcomeScreenSeen return (
? ( <div className="first-time-flow">
<div className="first-time-flow"> <Switch>
<Switch> <Route exact path={INITIALIZE_IMPORT_ACCOUNT_ROUTE} component={ImportAccountScreen} />
<Route exact path={INITIALIZE_IMPORT_ACCOUNT_ROUTE} component={ImportAccountScreen} /> <Route
<Route exact
exact path={INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE}
path={INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE} component={ImportSeedPhraseScreen}
component={ImportSeedPhraseScreen} />
/> <Route exact path={INITIALIZE_UNIQUE_IMAGE_ROUTE} component={UniqueImageScreen} />
<Route exact path={INITIALIZE_ROUTE} component={CreatePasswordScreen} /> <Route exact path={INITIALIZE_NOTICE_ROUTE} component={NoticeScreen} />
</Switch> <Route exact path={INITIALIZE_BACKUP_PHRASE_ROUTE} component={BackupPhraseScreen} />
</div> <Route exact path={INITIALIZE_CONFIRM_SEED_ROUTE} component={ConfirmSeed} />
) <Route exact path={INITIALIZE_CREATE_PASSWORD_ROUTE} component={CreatePasswordScreen} />
: <Redirect to={WELCOME_ROUTE } /> <Route exact path={INITIALIZE_ROUTE} component={WelcomeScreen} />
</Switch>
</div>
)
} }
} }

@ -2,11 +2,17 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Markdown from 'react-markdown' import Markdown from 'react-markdown'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
import { compose } from 'recompose'
import debounce from 'lodash.debounce' import debounce from 'lodash.debounce'
import { markNoticeRead } from '../../../../ui/app/actions' import { markNoticeRead } from '../../../../ui/app/actions'
import Identicon from '../../../../ui/app/components/identicon' import Identicon from '../../../../ui/app/components/identicon'
import Breadcrumbs from './breadcrumbs' 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' import LoadingScreen from './loading-screen'
class NoticeScreen extends Component { class NoticeScreen extends Component {
@ -25,6 +31,7 @@ class NoticeScreen extends Component {
markNoticeRead: PropTypes.func, markNoticeRead: PropTypes.func,
history: PropTypes.object, history: PropTypes.object,
isLoading: PropTypes.bool, isLoading: PropTypes.bool,
noActiveNotices: PropTypes.bool,
}; };
static defaultProps = { static defaultProps = {
@ -35,14 +42,27 @@ class NoticeScreen extends Component {
atBottom: false, 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() this.onScroll()
} }
acceptTerms = () => { acceptTerms = () => {
const { markNoticeRead, lastUnreadNotice, history } = this.props const { markNoticeRead, lastUnreadNotice, history } = this.props
markNoticeRead(lastUnreadNotice) 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(() => { onScroll = debounce(() => {
@ -98,12 +118,24 @@ class NoticeScreen extends Component {
} }
} }
export default connect( const mapStateToProps = ({ metamask, appState }) => {
({ metamask: { selectedAddress, lastUnreadNotice }, appState: { isLoading } }) => ({ const { selectedAddress, lastUnreadNotice, noActiveNotices } = metamask
lastUnreadNotice, const { isLoading } = appState
return {
address: selectedAddress, address: selectedAddress,
}), lastUnreadNotice,
dispatch => ({ noActiveNotices,
markNoticeRead: notice => dispatch(markNoticeRead(notice)), isLoading,
}) }
}
export default compose(
withRouter,
connect(
mapStateToProps,
dispatch => ({
markNoticeRead: notice => dispatch(markNoticeRead(notice)),
})
)
)(NoticeScreen) )(NoticeScreen)

@ -2,11 +2,12 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import classnames from 'classnames' 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 Identicon from '../../../../ui/app/components/identicon'
import Breadcrumbs from './breadcrumbs' import Breadcrumbs from './breadcrumbs'
import LoadingScreen from './loading-screen' 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 => ( const LockIcon = props => (
<svg <svg
@ -105,14 +106,6 @@ class BackupPhraseScreen extends Component {
WARNING: Never disclose your backup phrase. Anyone with this phrase can take your Ether forever. WARNING: Never disclose your backup phrase. Anyone with this phrase can take your Ether forever.
</div> </div>
{this.renderSecretWordsContainer()} {this.renderSecretWordsContainer()}
<button
className="first-time-flow__button"
onClick={() => isShowingSecret && history.push(CONFIRM_SEED_ROUTE)}
disabled={!isShowingSecret}
>
Next
</button>
<Breadcrumbs total={3} currentIndex={1} />
</div> </div>
<div className="backup-phrase__tips"> <div className="backup-phrase__tips">
<div className="backup-phrase__tips-text">Tips:</div> <div className="backup-phrase__tips-text">Tips:</div>
@ -129,10 +122,7 @@ class BackupPhraseScreen extends Component {
<div className="backup-phrase__next-button"> <div className="backup-phrase__next-button">
<button <button
className="first-time-flow__button" className="first-time-flow__button"
onClick={() => isShowingSecret && this.setState({ onClick={() => isShowingSecret && history.push(INITIALIZE_CONFIRM_SEED_ROUTE)}
isShowingSecret: false,
page: BackupPhraseScreen.PAGE.CONFIRM,
})}
disabled={!isShowingSecret} disabled={!isShowingSecret}
> >
Next Next
@ -160,7 +150,7 @@ class BackupPhraseScreen extends Component {
} }
export default compose( export default compose(
onlyUpdateForPropTypes, withRouter,
connect( connect(
({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({ ({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({
seedWords, seedWords,

@ -1,13 +1,16 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { withRouter } from 'react-router-dom'
import { compose } from 'recompose'
import {connect} from 'react-redux' import {connect} from 'react-redux'
import Identicon from '../../../../ui/app/components/identicon' import Identicon from '../../../../ui/app/components/identicon'
import Breadcrumbs from './breadcrumbs' import Breadcrumbs from './breadcrumbs'
import { INITIALIZE_NOTICE_ROUTE } from '../../../../ui/app/routes'
class UniqueImageScreen extends Component { class UniqueImageScreen extends Component {
static propTypes = { static propTypes = {
address: PropTypes.string, address: PropTypes.string,
next: PropTypes.func.isRequired, history: PropTypes.object,
} }
render () { render () {
@ -25,7 +28,7 @@ class UniqueImageScreen extends Component {
</div> </div>
<button <button
className="first-time-flow__button" className="first-time-flow__button"
onClick={this.props.next} onClick={() => this.props.history.push(INITIALIZE_NOTICE_ROUTE)}
> >
Next Next
</button> </button>
@ -37,8 +40,11 @@ class UniqueImageScreen extends Component {
} }
} }
export default connect( export default compose(
({ metamask: { selectedAddress } }) => ({ withRouter,
address: selectedAddress, connect(
}) ({ metamask: { selectedAddress } }) => ({
address: selectedAddress,
})
)
)(UniqueImageScreen) )(UniqueImageScreen)

@ -1322,12 +1322,13 @@ function markNoticeRead (notice) {
dispatch(actions.displayWarning(err)) dispatch(actions.displayWarning(err))
return reject(err) return reject(err)
} }
if (notice) { if (notice) {
dispatch(actions.showNotice(notice)) dispatch(actions.showNotice(notice))
resolve() resolve(true)
} else { } else {
dispatch(actions.clearNotices()) dispatch(actions.clearNotices())
resolve() resolve(false)
} }
}) })
}) })

@ -88,34 +88,18 @@ class App extends Component {
return ( return (
h(Switch, [ h(Switch, [
h(Route, { h(Route, { path: INITIALIZE_ROUTE, component: InitializeScreen }),
path: WELCOME_ROUTE,
exact,
component: WelcomeScreen,
}),
h(Route, {
path: INITIALIZE_ROUTE,
component: InitializeScreen,
}),
h(Initialized, { h(Initialized, {
path: REVEAL_SEED_ROUTE, path: REVEAL_SEED_ROUTE,
exact, exact,
component: RevealSeedPage, component: RevealSeedPage,
mascaraComponent: MascaraSeedScreen, mascaraComponent: MascaraSeedScreen,
}), }),
h(Initialized, { // h(Initialized, { path: CONFIRM_SEED_ROUTE, exact, component: MascaraConfirmSeedScreen }),
path: CONFIRM_SEED_ROUTE,
exact,
mascaraComponent: MascaraConfirmSeedScreen,
}),
h(Initialized, { path: UNLOCK_ROUTE, exact, component: UnlockPage }), h(Initialized, { path: UNLOCK_ROUTE, exact, component: UnlockPage }),
h(Initialized, { path: SETTINGS_ROUTE, component: Settings }), h(Initialized, { path: SETTINGS_ROUTE, component: Settings }),
h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }), h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }),
h(Initialized, { h(Initialized, { path: NOTICE_ROUTE, exact, component: NoticeScreen }),
path: NOTICE_ROUTE,
exact,
component: MascaraNoticeScreen,
}),
h(Authenticated, { path: CONFIRM_TRANSACTION_ROUTE, component: ConfirmTxScreen }), h(Authenticated, { path: CONFIRM_TRANSACTION_ROUTE, component: ConfirmTxScreen }),
h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen2 }), h(Authenticated, { path: SEND_ROUTE, exact, component: SendTransactionScreen2 }),
h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }), h(Authenticated, { path: ADD_TOKEN_ROUTE, exact, component: AddTokenPage }),
@ -322,7 +306,7 @@ class App extends Component {
]), ]),
isUnlocked && h('div.account-menu__icon', { onClick: this.context.toggleAccountMenu }, [ isUnlocked && h('div.account-menu__icon', { onClick: this.props.toggleAccountMenu }, [
h(Identicon, { h(Identicon, {
address: this.props.selectedAddress, address: this.props.selectedAddress,
diameter: 32, diameter: 32,

@ -384,7 +384,7 @@ AddTokenScreen.prototype.render = function () {
return h('div.add-token', [ return h('div.add-token', [
h('div.add-token__header', [ h('div.add-token__header', [
h('div.add-token__header__cancel', { h('div.add-token__header__cancel', {
onClick: () => history.goBack(), onClick: () => history.push(DEFAULT_ROUTE),
}, [ }, [
h('i.fa.fa-angle-left.fa-lg'), h('i.fa.fa-angle-left.fa-lg'),
h('span', this.context.t('cancel')), h('span', this.context.t('cancel')),
@ -417,7 +417,7 @@ AddTokenScreen.prototype.render = function () {
!isShowingConfirmation && h('div.add-token__buttons', [ !isShowingConfirmation && h('div.add-token__buttons', [
h('button.btn-secondary--lg.add-token__cancel-button', { h('button.btn-secondary--lg.add-token__cancel-button', {
onClick: () => history.goBack(), onClick: () => history.push(DEFAULT_ROUTE),
}, this.context.t('cancel')), }, this.context.t('cancel')),
h('button.btn-primary--lg.add-token__confirm-button', { h('button.btn-primary--lg.add-token__confirm-button', {
onClick: this.onNext, onClick: this.onNext,

@ -35,11 +35,11 @@ class Home extends Component {
unapprovedTypedMessagesCount = 0, unapprovedTypedMessagesCount = 0,
} = this.props } = this.props
console.log('IN HOME COMPONENDIMOUNT') console.log('HOME MOUNTED')
// unapprovedTxs and unapproved messages // unapprovedTxs and unapproved messages
if (Object.keys(unapprovedTxs).length || if (Object.keys(unapprovedTxs).length ||
unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) { unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) {
console.log('IN HOME SHOULD REDIRECT')
this.props.history.push(CONFIRM_TRANSACTION_ROUTE) this.props.history.push(CONFIRM_TRANSACTION_ROUTE)
} }
} }
@ -55,6 +55,15 @@ class Home extends Component {
seedWords, seedWords,
} = this.props } = this.props
// notices
if (!noActiveNotices || (lostAccounts && lostAccounts.length > 0)) {
return h(Redirect, {
to: {
pathname: NOTICE_ROUTE,
},
})
}
// seed words // seed words
if (seedWords) { if (seedWords) {
log.debug('rendering seed words') log.debug('rendering seed words')
@ -74,15 +83,6 @@ class Home extends Component {
}) })
} }
// notices
if (!noActiveNotices || (lostAccounts && lostAccounts.length > 0)) {
return h(Redirect, {
to: {
pathname: NOTICE_ROUTE,
},
})
}
// if (!props.noActiveNotices) { // if (!props.noActiveNotices) {
// log.debug('rendering notice screen for unread notices.') // log.debug('rendering notice screen for unread notices.')
// return h(NoticeScreen, { // return h(NoticeScreen, {

@ -24,7 +24,7 @@ class RestoreVaultPage extends PersistentForm {
cancel () { cancel () {
this.props.unMarkPasswordForgotten() this.props.unMarkPasswordForgotten()
.then(this.props.history.goBack()) .then(this.props.history.push(DEFAULT_ROUTE))
} }
createNewVaultAndRestore () { createNewVaultAndRestore () {

@ -133,7 +133,7 @@ class RevealSeedPage extends Component {
}, [ }, [
// cancel // cancel
h('button.primary', { h('button.primary', {
onClick: () => history.goBack(), onClick: () => history.push(DEFAULT_ROUTE),
}, 'CANCEL'), }, 'CANCEL'),
// submit // submit

@ -14,9 +14,13 @@ const SIGNATURE_REQUEST_ROUTE = '/confirm-transaction/signature-request'
const NOTICE_ROUTE = '/notice' const NOTICE_ROUTE = '/notice'
const WELCOME_ROUTE = '/welcome' const WELCOME_ROUTE = '/welcome'
const INITIALIZE_ROUTE = '/initialize' const INITIALIZE_ROUTE = '/initialize'
const INITIALIZE_CREATE_PASSWORD_ROUTE = '/initialize/create-password'
const INITIALIZE_IMPORT_ACCOUNT_ROUTE = '/initialize/import-account' const INITIALIZE_IMPORT_ACCOUNT_ROUTE = '/initialize/import-account'
const INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE = '/initialize/import-with-seed-phrase' const INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE = '/initialize/import-with-seed-phrase'
const INITIALIZE_UNIQUE_IMAGE_ROUTE = '/initialize/unique-image' const INITIALIZE_UNIQUE_IMAGE_ROUTE = '/initialize/unique-image'
const INITIALIZE_NOTICE_ROUTE = '/initialize/notice'
const INITIALIZE_BACKUP_PHRASE_ROUTE = '/initialize/backup-phrase'
const INITIALIZE_CONFIRM_SEED_ROUTE = '/initialize/confirm-phrase'
module.exports = { module.exports = {
DEFAULT_ROUTE, DEFAULT_ROUTE,
@ -35,7 +39,11 @@ module.exports = {
SIGNATURE_REQUEST_ROUTE, SIGNATURE_REQUEST_ROUTE,
WELCOME_ROUTE, WELCOME_ROUTE,
INITIALIZE_ROUTE, INITIALIZE_ROUTE,
INITIALIZE_CREATE_PASSWORD_ROUTE,
INITIALIZE_IMPORT_ACCOUNT_ROUTE, INITIALIZE_IMPORT_ACCOUNT_ROUTE,
INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE,
INITIALIZE_UNIQUE_IMAGE_ROUTE, INITIALIZE_UNIQUE_IMAGE_ROUTE,
INITIALIZE_NOTICE_ROUTE,
INITIALIZE_BACKUP_PHRASE_ROUTE,
INITIALIZE_CONFIRM_SEED_ROUTE,
} }

@ -29,7 +29,7 @@ const {
isTokenBalanceSufficient, isTokenBalanceSufficient,
} = require('./components/send/send-utils') } = require('./components/send/send-utils')
const { isValidAddress } = require('./util') const { isValidAddress } = require('./util')
const { CONFIRM_TRANSACTION_ROUTE } = require('./routes') const { CONFIRM_TRANSACTION_ROUTE, DEFAULT_ROUTE } = require('./routes')
SendTransactionScreen.contextTypes = { SendTransactionScreen.contextTypes = {
t: PropTypes.func, t: PropTypes.func,
@ -201,7 +201,7 @@ SendTransactionScreen.prototype.renderHeader = function () {
h('div.page-container__header-close', { h('div.page-container__header-close', {
onClick: () => { onClick: () => {
clearSend() clearSend()
history.goBack() history.push(DEFAULT_ROUTE)
}, },
}), }),
@ -521,7 +521,7 @@ SendTransactionScreen.prototype.renderFooter = function () {
h('button.btn-secondary--lg.page-container__footer-button', { h('button.btn-secondary--lg.page-container__footer-button', {
onClick: () => { onClick: () => {
clearSend() clearSend()
history.goBack() history.push(DEFAULT_ROUTE)
}, },
}, this.context.t('cancel')), }, this.context.t('cancel')),
h('button.btn-primary--lg.page-container__footer-button', { h('button.btn-primary--lg.page-container__footer-button', {

@ -3,9 +3,11 @@ import h from 'react-hyperscript'
import { Component } from 'react' import { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import {connect} from 'react-redux' import {connect} from 'react-redux'
import { withRouter } from 'react-router-dom'
import { compose } from 'recompose'
import {closeWelcomeScreen} from './actions' import {closeWelcomeScreen} from './actions'
import Mascot from './components/mascot' import Mascot from './components/mascot'
import { INITIALIZE_ROUTE } from './routes' import { INITIALIZE_CREATE_PASSWORD_ROUTE } from './routes'
class WelcomeScreen extends Component { class WelcomeScreen extends Component {
static propTypes = { static propTypes = {
@ -18,9 +20,18 @@ class WelcomeScreen extends Component {
this.animationEventEmitter = new EventEmitter() this.animationEventEmitter = new EventEmitter()
} }
componentWillMount () {
const { history, welcomeScreenSeen } = this.props
if (welcomeScreenSeen) {
console.log('SEENT', welcomeScreenSeen)
history.push(INITIALIZE_CREATE_PASSWORD_ROUTE)
}
}
initiateAccountCreation = () => { initiateAccountCreation = () => {
this.props.closeWelcomeScreen() this.props.closeWelcomeScreen()
this.props.history.push(INITIALIZE_ROUTE) this.props.history.push(INITIALIZE_CREATE_PASSWORD_ROUTE)
} }
render () { render () {
@ -51,9 +62,18 @@ class WelcomeScreen extends Component {
} }
} }
export default connect( const mapStateToProps = ({ metamask: { welcomeScreenSeen } }) => {
null, return {
dispatch => ({ welcomeScreenSeen,
closeWelcomeScreen: () => dispatch(closeWelcomeScreen()), }
}) }
export default compose(
withRouter,
connect(
mapStateToProps,
dispatch => ({
closeWelcomeScreen: () => dispatch(closeWelcomeScreen()),
})
)
)(WelcomeScreen) )(WelcomeScreen)

Loading…
Cancel
Save