aboutsummaryrefslogtreecommitdiffstats
path: root/mascara
diff options
context:
space:
mode:
authorAlexander Tseung <alextsg@users.noreply.github.com>2018-03-07 01:14:57 +0800
committerGitHub <noreply@github.com>2018-03-07 01:14:57 +0800
commit5f8a632fec0e83b148e4e0b7fc95339fb870d804 (patch)
treed2d0fbe89aab50636df4d0412798be3732984f22 /mascara
parent9734969e5d09e73778f18e9842ecb4677589a722 (diff)
downloadtangerine-wallet-browser-5f8a632fec0e83b148e4e0b7fc95339fb870d804.tar.gz
tangerine-wallet-browser-5f8a632fec0e83b148e4e0b7fc95339fb870d804.tar.zst
tangerine-wallet-browser-5f8a632fec0e83b148e4e0b7fc95339fb870d804.zip
Fix seed phrase validation clearing form (#3417)
* Fix seed phrase validation clearing form * Make new ui import seed error feedback live, and allow newlines with and without carriage returns.
Diffstat (limited to 'mascara')
-rw-r--r--mascara/src/app/first-time/import-seed-phrase-screen.js191
-rw-r--r--mascara/src/app/first-time/index.css16
2 files changed, 123 insertions, 84 deletions
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 93c3f9203..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,13 +1,12 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
-import LoadingScreen from './loading-screen'
+import classnames from 'classnames'
import {
createNewVaultAndRestore,
hideWarning,
displayWarning,
unMarkPasswordForgotten,
- clearNotices,
} from '../../../../ui/app/actions'
class ImportSeedPhraseScreen extends Component {
@@ -17,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 = {
@@ -27,98 +26,130 @@ class ImportSeedPhraseScreen extends Component {
confirmPassword: '',
}
- onClick = () => {
- const { password, seedPhrase, confirmPassword } = this.state
- const { createNewVaultAndRestore, next, displayWarning, leaveImportSeedScreenState } = 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
+
+ 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, seedPhrase)
+ 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})}
- />
- </div>
- <button
- className="first-time-flow__button"
- onClick={this.onClick}
- >
- Import
- </button>
+ 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.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="import-account__input-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>
+ )
}
}
export default connect(
- ({ appState: { isLoading, warning } }) => ({ isLoading, warning }),
+ ({ appState: { warning } }) => ({ warning }),
dispatch => ({
leaveImportSeedScreenState: () => {
dispatch(unMarkPasswordForgotten())
diff --git a/mascara/src/app/first-time/index.css b/mascara/src/app/first-time/index.css
index 109946e1d..f59eb4ce1 100644
--- a/mascara/src/app/first-time/index.css
+++ b/mascara/src/app/first-time/index.css
@@ -1,11 +1,11 @@
.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 {
@@ -45,12 +45,12 @@
.buy-ether {
display: flex;
flex-flow: column nowrap;
- margin: 67px 0 50px 146px;
+ margin: 67px 0 50px;
max-width: 35rem;
}
.create-password {
- margin: 67px 0 50px 0px;
+ margin: 67px 0 50px;
}
.import-account {
@@ -418,6 +418,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;
}
@@ -564,6 +568,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;