mirror of
https://github.com/trezor/trezor-wallet
synced 2024-11-28 03:08:30 +00:00
Merge pull request #88 from satoshilabs/cleanup-passphrase-code
enhancement: rewrite passphrase modal
This commit is contained in:
commit
2ff639fbdf
@ -2,13 +2,13 @@ import React from 'react';
|
|||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import { TRANSITION } from 'config/variables';
|
import { TRANSITION, FONT_WEIGHT, FONT_SIZE } from 'config/variables';
|
||||||
|
|
||||||
const Wrapper = styled.button`
|
const Wrapper = styled.button`
|
||||||
padding: ${props => (props.icon ? '4px 24px 4px 15px' : '11px 24px')};
|
padding: ${props => (props.icon ? '4px 24px 4px 15px' : '11px 24px')};
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
font-size: 14px;
|
font-size: ${FONT_SIZE.SMALL};
|
||||||
font-weight: 300;
|
font-weight: ${FONT_WEIGHT.SMALLEST};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: ${colors.GREEN_PRIMARY};
|
background: ${colors.GREEN_PRIMARY};
|
||||||
color: ${colors.WHITE};
|
color: ${colors.WHITE};
|
||||||
|
@ -26,18 +26,18 @@ const IconWrapper = styled.div`
|
|||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: ${props => (props.checked ? colors.WHITE : colors.GREEN_PRIMARY)};
|
color: ${props => (props.isChecked ? colors.WHITE : colors.GREEN_PRIMARY)};
|
||||||
background: ${props => (props.checked ? colors.GREEN_PRIMARY : colors.WHITE)};
|
background: ${props => (props.isChecked ? colors.GREEN_PRIMARY : colors.WHITE)};
|
||||||
border: 1px solid ${props => (props.checked ? colors.GREEN_PRIMARY : colors.DIVIDER)};
|
border: 1px solid ${props => (props.isChecked ? colors.GREEN_PRIMARY : colors.DIVIDER)};
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
${props => !props.checked && css`
|
${props => !props.isChecked && css`
|
||||||
border: 1px solid ${colors.GREEN_PRIMARY};
|
border: 1px solid ${colors.GREEN_PRIMARY};
|
||||||
`}
|
`}
|
||||||
background: ${props => (props.checked ? colors.GREEN_PRIMARY : colors.WHITE)};
|
background: ${props => (props.isChecked ? colors.GREEN_PRIMARY : colors.WHITE)};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ const Label = styled.div`
|
|||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
color: ${props => (props.checked ? colors.TEXT_PRIMARY : colors.TEXT_PRIMARY)};
|
color: ${props => (props.isChecked ? colors.TEXT_PRIMARY : colors.TEXT_PRIMARY)};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ class Checkbox extends PureComponent {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
checked,
|
isChecked,
|
||||||
children,
|
children,
|
||||||
onClick,
|
onClick,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@ -73,20 +73,20 @@ class Checkbox extends PureComponent {
|
|||||||
onKeyUp={e => this.handleKeyboard(e)}
|
onKeyUp={e => this.handleKeyboard(e)}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
<IconWrapper checked={checked}>
|
<IconWrapper isChecked={isChecked}>
|
||||||
{checked && (
|
{isChecked && (
|
||||||
<Tick>
|
<Tick>
|
||||||
<Icon
|
<Icon
|
||||||
hoverColor={colors.WHITE}
|
hoverColor={colors.WHITE}
|
||||||
size={26}
|
size={26}
|
||||||
color={checked ? colors.WHITE : colors.GREEN_PRIMARY}
|
color={isChecked ? colors.WHITE : colors.GREEN_PRIMARY}
|
||||||
icon={icons.SUCCESS}
|
icon={icons.SUCCESS}
|
||||||
/>
|
/>
|
||||||
</Tick>
|
</Tick>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
<Label checked={checked}>{children}</Label>
|
<Label isChecked={isChecked}>{children}</Label>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ class Checkbox extends PureComponent {
|
|||||||
|
|
||||||
Checkbox.propTypes = {
|
Checkbox.propTypes = {
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
checked: PropTypes.bool,
|
isChecked: PropTypes.bool,
|
||||||
children: PropTypes.string,
|
children: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,14 +117,15 @@ class Input extends Component {
|
|||||||
hasAddon={!!this.props.sideAddons}
|
hasAddon={!!this.props.sideAddons}
|
||||||
type={this.props.type}
|
type={this.props.type}
|
||||||
placeholder={this.props.placeholder}
|
placeholder={this.props.placeholder}
|
||||||
autoComplete={this.props.autoComplete}
|
autocomplete={this.props.autocomplete}
|
||||||
autoCorrect={this.props.autoCorrect}
|
autocorrect={this.props.autocorrect}
|
||||||
autoCapitalize={this.props.autoCapitalize}
|
autocapitalize={this.props.autocapitalize}
|
||||||
spellCheck={this.props.spellCheck}
|
spellCheck={this.props.spellCheck}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
onChange={this.props.onChange}
|
onChange={this.props.onChange}
|
||||||
borderColor={this.getColor(this.props.state)}
|
borderColor={this.getColor(this.props.state)}
|
||||||
disabled={this.props.isDisabled}
|
disabled={this.props.isDisabled}
|
||||||
|
name={this.props.name}
|
||||||
/>
|
/>
|
||||||
</InputIconWrapper>
|
</InputIconWrapper>
|
||||||
{this.props.sideAddons && this.props.sideAddons.map(sideAddon => sideAddon)}
|
{this.props.sideAddons && this.props.sideAddons.map(sideAddon => sideAddon)}
|
||||||
@ -146,9 +147,9 @@ Input.propTypes = {
|
|||||||
innerRef: PropTypes.func,
|
innerRef: PropTypes.func,
|
||||||
placeholder: PropTypes.string,
|
placeholder: PropTypes.string,
|
||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
autoComplete: PropTypes.string,
|
autocomplete: PropTypes.string,
|
||||||
autoCorrect: PropTypes.string,
|
autocorrect: PropTypes.string,
|
||||||
autoCapitalize: PropTypes.string,
|
autocapitalize: PropTypes.string,
|
||||||
spellCheck: PropTypes.string,
|
spellCheck: PropTypes.string,
|
||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
@ -157,6 +158,7 @@ Input.propTypes = {
|
|||||||
topLabel: PropTypes.node,
|
topLabel: PropTypes.node,
|
||||||
sideAddons: PropTypes.arrayOf(PropTypes.node),
|
sideAddons: PropTypes.arrayOf(PropTypes.node),
|
||||||
isDisabled: PropTypes.bool,
|
isDisabled: PropTypes.bool,
|
||||||
|
name: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
Input.defaultProps = {
|
Input.defaultProps = {
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import raf from 'raf';
|
import styled from 'styled-components';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
|
import { FONT_SIZE, TRANSITION } from 'config/variables';
|
||||||
import { H2 } from 'components/Heading';
|
import { H2 } from 'components/Heading';
|
||||||
import P from 'components/Paragraph';
|
import P from 'components/Paragraph';
|
||||||
import { FONT_SIZE } from 'config/variables';
|
|
||||||
import Link from 'components/Link';
|
|
||||||
import Checkbox from 'components/Checkbox';
|
import Checkbox from 'components/Checkbox';
|
||||||
import Button from 'components/Button';
|
import Button from 'components/Button';
|
||||||
import Input from 'components/inputs/Input';
|
import Input from 'components/inputs/Input';
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import type { Props } from '../../index';
|
import type { Props } from '../../index';
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
deviceLabel: string,
|
||||||
|
shouldShowSingleInput: boolean,
|
||||||
|
passphraseInputValue: string,
|
||||||
|
passphraseCheckInputValue: string,
|
||||||
|
doPassphraseInputsMatch: boolean,
|
||||||
|
isPassphraseHidden: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
padding: 24px 48px;
|
padding: 24px 48px;
|
||||||
max-width: 390px;
|
max-width: 390px;
|
||||||
@ -45,315 +52,229 @@ const Footer = styled.div`
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type State = {
|
const LinkButton = styled(Button)`
|
||||||
deviceLabel: string;
|
padding: 0;
|
||||||
singleInput: boolean;
|
margin: 0;
|
||||||
passphrase: string;
|
text-decoration: none;
|
||||||
passphraseRevision: string;
|
cursor: pointer;
|
||||||
passphraseFocused: boolean;
|
transition: ${TRANSITION.HOVER};
|
||||||
passphraseRevisionFocused: boolean;
|
font-size: ${FONT_SIZE.SMALLER};
|
||||||
passphraseRevisionTouched: boolean;
|
border-radius: 0;
|
||||||
match: boolean;
|
border-bottom: 1px solid ${colors.GREEN_PRIMARY};
|
||||||
visible: boolean;
|
background: transparent;
|
||||||
}
|
|
||||||
|
|
||||||
export default class PinModal extends Component<Props, State> {
|
&,
|
||||||
|
&:visited,
|
||||||
|
&:active,
|
||||||
|
&:hover {
|
||||||
|
color: ${colors.GREEN_PRIMARY};
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: transparent;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
class Passphrase extends Component<Props, State> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const device = props.modal.opened ? props.modal.device : null;
|
const device = props.modal.opened ? props.modal.device : null;
|
||||||
if (!device) return;
|
if (!device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// check if this device is already known
|
// Check if this device is already known
|
||||||
const selected = props.wallet.selectedDevice;
|
// if device is already known then only one input is presented
|
||||||
|
const { selectedDevice } = props.wallet;
|
||||||
let deviceLabel = device.label;
|
let deviceLabel = device.label;
|
||||||
let singleInput = false;
|
let shouldShowSingleInput = false;
|
||||||
if (selected && selected.path === device.path) {
|
if (selectedDevice && selectedDevice.path === device.path) {
|
||||||
deviceLabel = selected.instanceLabel;
|
deviceLabel = selectedDevice.instanceLabel;
|
||||||
singleInput = selected.remember || selected.state !== null;
|
shouldShowSingleInput = selectedDevice.remember || selectedDevice.state !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
deviceLabel,
|
deviceLabel,
|
||||||
singleInput,
|
shouldShowSingleInput,
|
||||||
passphrase: '',
|
passphraseInputValue: '',
|
||||||
passphraseRevision: '',
|
passphraseCheckInputValue: '',
|
||||||
passphraseFocused: false,
|
doPassphraseInputsMatch: true,
|
||||||
passphraseRevisionFocused: false,
|
isPassphraseHidden: true,
|
||||||
passphraseRevisionTouched: false,
|
|
||||||
match: true,
|
|
||||||
visible: false,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboardHandler: (event: KeyboardEvent) => void;
|
|
||||||
|
|
||||||
state: State;
|
state: State;
|
||||||
|
|
||||||
passphraseInput: ?HTMLInputElement;
|
componentDidMount() {
|
||||||
|
this.passphraseInput.focus();
|
||||||
|
|
||||||
passphraseRevisionInput: ?HTMLInputElement;
|
this.handleKeyPress = this.handleKeyPress.bind(this);
|
||||||
|
window.addEventListener('keypress', this.handleKeyPress, false);
|
||||||
|
|
||||||
keyboardHandler(event: KeyboardEvent): void {
|
|
||||||
if (event.keyCode === 13) {
|
|
||||||
event.preventDefault();
|
|
||||||
//this.passphraseInput.blur();
|
|
||||||
//this.passphraseRevisionInput.blur();
|
|
||||||
|
|
||||||
//this.passphraseInput.type = 'text';
|
|
||||||
//this.passphraseRevisionInput.type = 'text';
|
|
||||||
|
|
||||||
this.submit();
|
|
||||||
|
|
||||||
// TODO: set timeout, or wait for blur event
|
|
||||||
//onPassphraseSubmit(passphrase, passphraseCached);
|
|
||||||
//raf(() => onPassphraseSubmit(passphrase));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
componentDidMount(): void {
|
window.removeEventListener('keypress', this.handleKeyPress, false);
|
||||||
// one time autofocus
|
|
||||||
if (this.passphraseInput) this.passphraseInput.focus();
|
|
||||||
this.keyboardHandler = this.keyboardHandler.bind(this);
|
|
||||||
window.addEventListener('keydown', this.keyboardHandler, false);
|
|
||||||
|
|
||||||
|
|
||||||
// document.oncontextmenu = (event) => {
|
|
||||||
// const el = window.event.srcElement || event.target;
|
|
||||||
// const type = el.tagName.toLowerCase() || '';
|
|
||||||
// if (type === 'input') {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we don't want to keep password inside "value" attribute,
|
handleKeyPress: (event: KeyboardEvent) => void;
|
||||||
// so we need to replace it thru javascript
|
|
||||||
componentDidUpdate() {
|
|
||||||
const {
|
|
||||||
passphrase,
|
|
||||||
passphraseRevision,
|
|
||||||
passphraseFocused,
|
|
||||||
passphraseRevisionFocused,
|
|
||||||
visible,
|
|
||||||
} = this.state;
|
|
||||||
// } = this.props.modal;
|
|
||||||
|
|
||||||
const passphraseInputValue: string = passphrase;
|
passphraseInput: HTMLInputElement;
|
||||||
const passphraseRevisionInputValue: string = passphraseRevision;
|
|
||||||
// if (!visible && !passphraseFocused) {
|
|
||||||
// passphraseInputValue = passphrase.replace(/./g, '•');
|
|
||||||
// }
|
|
||||||
// if (!visible && !passphraseRevisionFocused) {
|
|
||||||
// passphraseRevisionInputValue = passphraseRevision.replace(/./g, '•');
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
handleInputChange(event: Event) {
|
||||||
|
const { target } = event;
|
||||||
|
if (target instanceof HTMLInputElement) {
|
||||||
|
const inputValue = target.value;
|
||||||
|
const inputName = target.name;
|
||||||
|
|
||||||
if (this.passphraseInput) {
|
let doPassphraseInputsMatch = false;
|
||||||
// this.passphraseInput.value = passphraseInputValue;
|
if (inputName === 'passphraseInputValue') {
|
||||||
// this.passphraseInput.setAttribute('type', visible || (!visible && !passphraseFocused) ? 'text' : 'password');
|
// If passphrase is not hidden the second input should get filled automatically
|
||||||
this.passphraseInput.setAttribute('type', visible ? 'text' : 'password');
|
// and should be disabled
|
||||||
}
|
if (this.state.isPassphraseHidden) {
|
||||||
if (this.passphraseRevisionInput) {
|
doPassphraseInputsMatch = inputValue === this.state.passphraseCheckInputValue;
|
||||||
// this.passphraseRevisionInput.value = passphraseRevisionInputValue;
|
} else {
|
||||||
// this.passphraseRevisionInput.setAttribute('type', visible || (!visible && !passphraseRevisionFocused) ? 'text' : 'password');
|
// Since both inputs are same they really do match
|
||||||
this.passphraseRevisionInput.setAttribute('type', visible ? 'text' : 'password');
|
// see: comment above
|
||||||
}
|
this.setState({
|
||||||
}
|
passphraseCheckInputValue: inputValue,
|
||||||
|
});
|
||||||
componentWillUnmount(): void {
|
doPassphraseInputsMatch = true;
|
||||||
window.removeEventListener('keydown', this.keyboardHandler, false);
|
}
|
||||||
// this.passphraseInput.type = 'text';
|
} else if (inputName === 'passphraseCheckInputValue') {
|
||||||
// this.passphraseInput.style.display = 'none';
|
doPassphraseInputsMatch = inputValue === this.state.passphraseInputValue;
|
||||||
// this.passphraseRevisionInput.type = 'text';
|
|
||||||
// this.passphraseRevisionInput.style.display = 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
onPassphraseChange = (input: string, value: string): void => {
|
|
||||||
// https://codepen.io/MiDri/pen/PGqvrO
|
|
||||||
// or
|
|
||||||
// https://github.com/zakangelle/react-password-mask/blob/master/src/index.js
|
|
||||||
if (input === 'passphrase') {
|
|
||||||
this.setState(previousState => ({
|
|
||||||
match: previousState.singleInput || previousState.passphraseRevision === value,
|
|
||||||
passphrase: value,
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (this.state.visible && this.passphraseRevisionInput) {
|
|
||||||
this.setState({
|
|
||||||
match: true,
|
|
||||||
passphraseRevision: value,
|
|
||||||
});
|
|
||||||
this.passphraseRevisionInput.value = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.state.shouldShowSingleInput) {
|
||||||
|
doPassphraseInputsMatch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
[inputName]: inputValue,
|
||||||
|
doPassphraseInputsMatch,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCheckboxClick() {
|
||||||
|
// If passphrase was visible and now shouldn't be --> delete the value of passphraseCheckInputValue
|
||||||
|
// doPassphraseInputsMatch
|
||||||
|
// - if passphrase was visible and now shouldn't be --> doPassphraseInputsMatch = false
|
||||||
|
// - because passphraseCheckInputValue will be empty string
|
||||||
|
// - if passphrase wasn't visibe and now should be --> doPassphraseInputsMatch = true
|
||||||
|
// - because passphraseCheckInputValue will be same as passphraseInputValue
|
||||||
|
let doInputsMatch = false;
|
||||||
|
if (this.state.shouldShowSingleInput || this.state.passphraseInputValue === this.state.passphraseCheckInputValue) {
|
||||||
|
doInputsMatch = true;
|
||||||
} else {
|
} else {
|
||||||
this.setState(previousState => ({
|
doInputsMatch = !!this.state.isPassphraseHidden;
|
||||||
match: previousState.passphrase === value,
|
|
||||||
passphraseRevision: value,
|
|
||||||
passphraseRevisionTouched: true,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setState(previousState => ({
|
||||||
|
isPassphraseHidden: !previousState.isPassphraseHidden,
|
||||||
|
passphraseInputValue: previousState.isPassphraseHidden ? previousState.passphraseInputValue : '',
|
||||||
|
passphraseCheckInputValue: previousState.isPassphraseHidden ? previousState.passphraseInputValue : '',
|
||||||
|
doPassphraseInputsMatch: doInputsMatch,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
onPassphraseFocus = (input: string): void => {
|
submitPassphrase(shouldLeavePassphraseBlank: boolean = false) {
|
||||||
if (input === 'passphrase') {
|
|
||||||
this.setState({
|
|
||||||
passphraseFocused: true,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
passphraseRevisionFocused: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onPassphraseBlur = (input: string): void => {
|
|
||||||
if (input === 'passphrase') {
|
|
||||||
this.setState({
|
|
||||||
passphraseFocused: false,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
passphraseRevisionFocused: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onPassphraseShow = (): void => {
|
|
||||||
this.setState({
|
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
if (this.passphraseRevisionInput) {
|
|
||||||
this.passphraseRevisionInput.disabled = true;
|
|
||||||
this.passphraseRevisionInput.value = this.state.passphrase;
|
|
||||||
this.setState(previousState => ({
|
|
||||||
passphraseRevision: previousState.passphrase,
|
|
||||||
match: true,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onPassphraseHide = (): void => {
|
|
||||||
this.setState({
|
|
||||||
visible: false,
|
|
||||||
});
|
|
||||||
if (this.passphraseRevisionInput) {
|
|
||||||
const emptyPassphraseRevisionValue = '';
|
|
||||||
this.passphraseRevisionInput.value = emptyPassphraseRevisionValue;
|
|
||||||
this.setState(previousState => ({
|
|
||||||
passphraseRevision: emptyPassphraseRevisionValue,
|
|
||||||
match: emptyPassphraseRevisionValue === previousState.passphrase,
|
|
||||||
}));
|
|
||||||
this.passphraseRevisionInput.disabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
submit = (empty: boolean = false): void => {
|
|
||||||
const { onPassphraseSubmit } = this.props.modalActions;
|
const { onPassphraseSubmit } = this.props.modalActions;
|
||||||
const { passphrase, match } = this.state;
|
const passphrase = this.state.passphraseInputValue;
|
||||||
|
|
||||||
if (!match) return;
|
|
||||||
|
|
||||||
//this.passphraseInput.type = 'text';
|
|
||||||
// this.passphraseInput.style.display = 'none';
|
|
||||||
//this.passphraseInput.setAttribute('readonly', 'readonly');
|
|
||||||
// this.passphraseRevisionInput.type = 'text';
|
|
||||||
//this.passphraseRevisionInput.style.display = 'none';
|
|
||||||
//this.passphraseRevisionInput.setAttribute('readonly', 'readonly');
|
|
||||||
|
|
||||||
// const p = passphrase;
|
|
||||||
|
|
||||||
|
// Reset state so same passphrase isn't filled when the modal will be visible again
|
||||||
this.setState({
|
this.setState({
|
||||||
passphrase: '',
|
passphraseInputValue: '',
|
||||||
passphraseRevision: '',
|
passphraseCheckInputValue: '',
|
||||||
passphraseFocused: false,
|
doPassphraseInputsMatch: true,
|
||||||
passphraseRevisionFocused: false,
|
isPassphraseHidden: true,
|
||||||
visible: false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
raf(() => onPassphraseSubmit(empty ? '' : passphrase));
|
onPassphraseSubmit(shouldLeavePassphraseBlank ? '' : passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleKeyPress(event: KeyboardEvent) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
console.warn('ENTER', this.state);
|
||||||
|
if (this.state.doPassphraseInputsMatch) {
|
||||||
|
this.submitPassphrase();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.props.modal.opened) return null;
|
if (!this.props.modal.opened) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
|
||||||
device,
|
|
||||||
} = this.props.modal;
|
|
||||||
|
|
||||||
const {
|
|
||||||
deviceLabel,
|
|
||||||
singleInput,
|
|
||||||
passphrase,
|
|
||||||
passphraseRevision,
|
|
||||||
passphraseFocused,
|
|
||||||
passphraseRevisionFocused,
|
|
||||||
visible,
|
|
||||||
match,
|
|
||||||
passphraseRevisionTouched,
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
let passphraseInputType: string = visible || (!visible && !passphraseFocused) ? 'text' : 'password';
|
|
||||||
let passphraseRevisionInputType: string = visible || (!visible && !passphraseRevisionFocused) ? 'text' : 'password';
|
|
||||||
passphraseInputType = passphraseRevisionInputType = 'text';
|
|
||||||
//let passphraseInputType: string = visible || passphraseFocused ? "text" : "password";
|
|
||||||
//let passphraseRevisionInputType: string = visible || passphraseRevisionFocused ? "text" : "password";
|
|
||||||
|
|
||||||
const showPassphraseCheckboxFn: Function = visible ? this.onPassphraseHide : this.onPassphraseShow;
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<H2>Enter { deviceLabel } passphrase</H2>
|
<H2>Enter {this.state.deviceLabel} passphrase</H2>
|
||||||
<P isSmaller>Note that passphrase is case-sensitive.</P>
|
<P isSmaller>Note that passphrase is case-sensitive.</P>
|
||||||
<Row>
|
<Row>
|
||||||
<Label>Passphrase</Label>
|
<Label>Passphrase</Label>
|
||||||
<Input
|
<Input
|
||||||
innerRef={(element) => { this.passphraseInput = element; }}
|
innerRef={(input) => { this.passphraseInput = input; }}
|
||||||
onChange={event => this.onPassphraseChange('passphrase', event.currentTarget.value)}
|
name="passphraseInputValue"
|
||||||
type={passphraseInputType}
|
type={this.state.isPassphraseHidden ? 'password' : 'text'}
|
||||||
autoComplete="off"
|
autocorrect="off"
|
||||||
autoCorrect="off"
|
autocapitalize="off"
|
||||||
autoCapitalize="off"
|
autocomplete="off"
|
||||||
spellCheck="false"
|
value={this.state.passphraseInputValue}
|
||||||
data-lpignore="true"
|
onChange={event => this.handleInputChange(event)}
|
||||||
onFocus={() => this.onPassphraseFocus('passphrase')}
|
|
||||||
onBlur={() => this.onPassphraseBlur('passphrase')}
|
|
||||||
tabIndex="0"
|
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
{!singleInput && (
|
{!this.state.shouldShowSingleInput && (
|
||||||
<Row>
|
<Row>
|
||||||
<Label>Re-enter passphrase</Label>
|
<Label>Re-enter passphrase</Label>
|
||||||
<Input
|
<Input
|
||||||
innerRef={(element) => { this.passphraseRevisionInput = element; }}
|
name="passphraseCheckInputValue"
|
||||||
onChange={event => this.onPassphraseChange('revision', event.currentTarget.value)}
|
type={this.state.isPassphraseHidden ? 'password' : 'text'}
|
||||||
type={passphraseRevisionInputType}
|
autocorrect="off"
|
||||||
autoComplete="off"
|
autocapitalize="off"
|
||||||
autoCorrect="off"
|
autocomplete="off"
|
||||||
autoCapitalize="off"
|
value={this.state.passphraseCheckInputValue}
|
||||||
spellCheck="false"
|
onChange={event => this.handleInputChange(event)}
|
||||||
data-lpignore="true"
|
isDisabled={!this.state.isPassphraseHidden}
|
||||||
onFocus={() => this.onPassphraseFocus('revision')}
|
|
||||||
onBlur={() => this.onPassphraseBlur('revision')}
|
|
||||||
/>
|
/>
|
||||||
{!match && passphraseRevisionTouched && <PassphraseError>Passphrases do not match</PassphraseError> }
|
|
||||||
</Row>
|
</Row>
|
||||||
) }
|
)}
|
||||||
|
|
||||||
|
{!this.state.doPassphraseInputsMatch && (
|
||||||
|
<PassphraseError>Passphrases do not match</PassphraseError>
|
||||||
|
)}
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Checkbox onClick={showPassphraseCheckboxFn} checked={visible}>Show passphrase</Checkbox>
|
<Checkbox
|
||||||
|
isChecked={!this.state.isPassphraseHidden}
|
||||||
|
onClick={() => this.handleCheckboxClick()}
|
||||||
|
>
|
||||||
|
Show passphrase
|
||||||
|
</Checkbox>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Button type="button" disabled={!match} onClick={() => this.submit()}>Enter</Button>
|
<Button
|
||||||
|
isDisabled={!this.state.doPassphraseInputsMatch}
|
||||||
|
onClick={() => this.submitPassphrase()}
|
||||||
|
>Enter
|
||||||
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Footer>
|
<Footer>
|
||||||
<P isSmaller>If you want to access your default account</P>
|
<P isSmaller>If you want to access your default account</P>
|
||||||
<P isSmaller>
|
<P isSmaller>
|
||||||
<Link isGreen onClick={() => this.submit(true)}>Leave passphrase blank</Link>
|
<LinkButton
|
||||||
|
isGreen
|
||||||
|
onClick={() => this.submitPassphrase(true)}
|
||||||
|
>Leave passphrase blank
|
||||||
|
</LinkButton>
|
||||||
</P>
|
</P>
|
||||||
</Footer>
|
</Footer>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default Passphrase;
|
Loading…
Reference in New Issue
Block a user