parent
fd4fbdc0cd
commit
1a9b217558
@ -0,0 +1,232 @@ |
||||
import React, {Component, PropTypes} from 'react' |
||||
import {connect} from 'react-redux'; |
||||
import classnames from 'classnames' |
||||
import Identicon from '../../../../ui/app/components/identicon' |
||||
import {confirmSeedWords} from '../../../../ui/app/actions' |
||||
import Breadcrumbs from './breadcrumbs' |
||||
|
||||
const LockIcon = props => ( |
||||
<svg |
||||
version="1.1" |
||||
id="Capa_1" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
xmlnsXlink="http://www.w3.org/1999/xlink" |
||||
x="0px" |
||||
y="0px" |
||||
width="401.998px" |
||||
height="401.998px" |
||||
viewBox="0 0 401.998 401.998" |
||||
style={{enableBackground: 'new 0 0 401.998 401.998'}} |
||||
xmlSpace="preserve" |
||||
{...props} |
||||
> |
||||
<g> |
||||
<path |
||||
d="M357.45,190.721c-5.331-5.33-11.8-7.993-19.417-7.993h-9.131v-54.821c0-35.022-12.559-65.093-37.685-90.218 |
||||
C266.093,12.563,236.025,0,200.998,0c-35.026,0-65.1,12.563-90.222,37.688C85.65,62.814,73.091,92.884,73.091,127.907v54.821 |
||||
h-9.135c-7.611,0-14.084,2.663-19.414,7.993c-5.33,5.326-7.994,11.799-7.994,19.417V374.59c0,7.611,2.665,14.086,7.994,19.417 |
||||
c5.33,5.325,11.803,7.991,19.414,7.991H338.04c7.617,0,14.085-2.663,19.417-7.991c5.325-5.331,7.994-11.806,7.994-19.417V210.135 |
||||
C365.455,202.523,362.782,196.051,357.45,190.721z M274.087,182.728H127.909v-54.821c0-20.175,7.139-37.402,21.414-51.675 |
||||
c14.277-14.275,31.501-21.411,51.678-21.411c20.179,0,37.399,7.135,51.677,21.411c14.271,14.272,21.409,31.5,21.409,51.675V182.728 |
||||
z" |
||||
/> |
||||
</g> |
||||
</svg> |
||||
); |
||||
|
||||
class BackupPhraseScreen extends Component { |
||||
static propTypes = { |
||||
address: PropTypes.string.isRequired, |
||||
seedWords: PropTypes.string.isRequired, |
||||
next: PropTypes.func.isRequired |
||||
}; |
||||
|
||||
static defaultProps = { |
||||
seedWords: '' |
||||
}; |
||||
|
||||
static PAGE = { |
||||
SECRET: 'secret', |
||||
CONFIRM: 'confirm' |
||||
}; |
||||
|
||||
state = { |
||||
isShowingSecret: false, |
||||
page: BackupPhraseScreen.PAGE.SECRET, |
||||
selectedSeeds: [] |
||||
} |
||||
|
||||
renderSecretWordsContainer() { |
||||
const { isShowingSecret } = this.state; |
||||
return ( |
||||
<div className="backup-phrase__secret"> |
||||
<div className={classnames('backup-phrase__secret-words', { |
||||
'backup-phrase__secret-words--hidden': !isShowingSecret |
||||
})}> |
||||
{this.props.seedWords} |
||||
</div> |
||||
{!isShowingSecret && ( |
||||
<div className="backup-phrase__secret-blocker"> |
||||
<LockIcon width="28px" height="35px" fill="#FFFFFF" /> |
||||
<button |
||||
className="backup-phrase__reveal-button" |
||||
onClick={() => this.setState({ isShowingSecret: true })} |
||||
> |
||||
Click here to reveal secret words |
||||
</button> |
||||
</div> |
||||
)} |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
renderSecretScreen() { |
||||
const { isShowingSecret } = this.state |
||||
return ( |
||||
<div className="backup-phrase__content-wrapper"> |
||||
<div> |
||||
<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. |
||||
</div> |
||||
<div className="backup-phrase__body-text"> |
||||
WARNING: Never disclose your backup phrase. Anyone with this phrase can take your Ether forever. |
||||
</div> |
||||
{this.renderSecretWordsContainer()} |
||||
<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 className="backup-phrase__tips"> |
||||
<div className="backup-phrase__tips-text">Tips:</div> |
||||
<div className="backup-phrase__tips-text"> |
||||
Store this phrase in a password manager like 1password. |
||||
</div> |
||||
<div className="backup-phrase__tips-text"> |
||||
Write this phrase on a piece of paper and store in a secure location. If you want even more security, write it down on multiple pieces of paper and store each in 2 - 3 different locations. |
||||
</div> |
||||
<div className="backup-phrase__tips-text"> |
||||
Memorize this phrase. |
||||
</div> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
renderConfirmationScreen() { |
||||
const { seedWords, confirmSeedWords, next } = this.props; |
||||
const { selectedSeeds } = this.state; |
||||
const isValid = seedWords === selectedSeeds.join(' ') |
||||
|
||||
return ( |
||||
<div className="backup-phrase__content-wrapper"> |
||||
<div> |
||||
<div className="backup-phrase__title">Confirm your Secret Backup Phrase</div> |
||||
<div className="backup-phrase__body-text"> |
||||
Please select each phrase in order to make sure it is correct. |
||||
</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"> |
||||
{seedWords.split(' ').map((word, i) => { |
||||
const isSelected = selectedSeeds.includes(word) |
||||
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, word] |
||||
}) |
||||
} else { |
||||
this.setState({ |
||||
selectedSeeds: selectedSeeds.filter(seed => seed !== word) |
||||
}) |
||||
} |
||||
}} |
||||
> |
||||
{word} |
||||
</button> |
||||
) |
||||
})} |
||||
</div> |
||||
<button |
||||
className="first-time-flow__button" |
||||
onClick={() => isValid && confirmSeedWords().then(next)} |
||||
disabled={!isValid} |
||||
> |
||||
Confirm |
||||
</button> |
||||
</div> |
||||
</div> |
||||
)
|
||||
} |
||||
|
||||
renderBack() { |
||||
return this.state.page === BackupPhraseScreen.PAGE.CONFIRM |
||||
? ( |
||||
<a |
||||
className="backup-phrase__back-button" |
||||
onClick={e => { |
||||
e.preventDefault() |
||||
this.setState({ |
||||
page: BackupPhraseScreen.PAGE.SECRET |
||||
}) |
||||
}} |
||||
href="#" |
||||
> |
||||
{`< Back`} |
||||
</a> |
||||
) |
||||
: null |
||||
} |
||||
|
||||
renderContent() { |
||||
switch(this.state.page) { |
||||
case BackupPhraseScreen.PAGE.CONFIRM: |
||||
return this.renderConfirmationScreen(); |
||||
case BackupPhraseScreen.PAGE.SECRET: |
||||
default: |
||||
return this.renderSecretScreen(); |
||||
} |
||||
} |
||||
|
||||
render() { |
||||
return ( |
||||
<div className="backup-phrase"> |
||||
{this.renderBack()} |
||||
<Identicon address={this.props.address} diameter={70} /> |
||||
{this.renderContent()} |
||||
</div> |
||||
) |
||||
} |
||||
} |
||||
|
||||
export default connect( |
||||
({ metamask: { selectedAddress, seedWords } }) => ({ |
||||
seedWords, |
||||
address: selectedAddress |
||||
}), |
||||
dispatch => ({ |
||||
confirmSeedWords: () => dispatch(confirmSeedWords()) |
||||
}) |
||||
)(BackupPhraseScreen) |
Loading…
Reference in new issue