mirror of
https://github.com/trezor/trezor-wallet
synced 2024-12-29 10:28:08 +00:00
refacotred modals components
This commit is contained in:
parent
49ca5992fd
commit
e59c9ec714
55
src/components/modals/Container.js
Normal file
55
src/components/modals/Container.js
Normal file
@ -0,0 +1,55 @@
|
||||
/* @flow */
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
import ModalActions from 'actions/ModalActions';
|
||||
import ReceiveActions from 'actions/ReceiveActions';
|
||||
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from 'flowtype';
|
||||
|
||||
import Modal from './index';
|
||||
|
||||
type OwnProps = { }
|
||||
|
||||
type StateProps = {
|
||||
modal: $ElementType<State, 'modal'>,
|
||||
accounts: $ElementType<State, 'accounts'>,
|
||||
devices: $ElementType<State, 'devices'>,
|
||||
connect: $ElementType<State, 'connect'>,
|
||||
selectedAccount: $ElementType<State, 'selectedAccount'>,
|
||||
sendForm: $ElementType<State, 'sendForm'>,
|
||||
receive: $ElementType<State, 'receive'>,
|
||||
localStorage: $ElementType<State, 'localStorage'>,
|
||||
wallet: $ElementType<State, 'wallet'>,
|
||||
}
|
||||
|
||||
type DispatchProps = {
|
||||
modalActions: typeof ModalActions,
|
||||
receiveActions: typeof ReceiveActions,
|
||||
}
|
||||
|
||||
export type Props = StateProps & DispatchProps;
|
||||
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State): StateProps => ({
|
||||
modal: state.modal,
|
||||
accounts: state.accounts,
|
||||
devices: state.devices,
|
||||
connect: state.connect,
|
||||
selectedAccount: state.selectedAccount,
|
||||
sendForm: state.sendForm,
|
||||
receive: state.receive,
|
||||
localStorage: state.localStorage,
|
||||
wallet: state.wallet,
|
||||
});
|
||||
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => ({
|
||||
modalActions: bindActionCreators(ModalActions, dispatch),
|
||||
receiveActions: bindActionCreators(ReceiveActions, dispatch),
|
||||
});
|
||||
|
||||
// export default connect(mapStateToProps, mapDispatchToProps)(Modal);
|
||||
export default withRouter(
|
||||
connect(mapStateToProps, mapDispatchToProps)(Modal),
|
||||
);
|
@ -1,13 +1,16 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import H3 from 'components/Heading';
|
||||
|
||||
import colors from 'config/colors';
|
||||
import P from 'components/Paragraph';
|
||||
import { FONT_SIZE } from 'config/variables';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
import H3 from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
|
||||
import type { Props } from '../../Container';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
width: 390px;
|
||||
@ -49,4 +52,8 @@ const ConfirmAddress = (props: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
ConfirmAddress.propTypes = {
|
||||
selectedAccount: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ConfirmAddress;
|
@ -1,16 +1,24 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import icons from 'config/icons';
|
||||
import colors from 'config/colors';
|
||||
import { LINE_HEIGHT } from 'config/variables';
|
||||
|
||||
import P from 'components/Paragraph';
|
||||
import Icon from 'components/Icon';
|
||||
import icons from 'config/icons';
|
||||
import { H3 } from 'components/Heading';
|
||||
import { LINE_HEIGHT } from 'config/variables';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
sendForm: $ElementType<BaseProps, 'sendForm'>;
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
width: 390px;
|
||||
@ -40,9 +48,6 @@ const Label = styled.div`
|
||||
`;
|
||||
|
||||
const ConfirmSignTx = (props: Props) => {
|
||||
if (props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
const { device } = props.modal;
|
||||
|
||||
const {
|
||||
amount,
|
||||
address,
|
||||
@ -54,7 +59,7 @@ const ConfirmSignTx = (props: Props) => {
|
||||
<Wrapper>
|
||||
<Header>
|
||||
<Icon icon={icons.T1} size={60} color={colors.TEXT_SECONDARY} />
|
||||
<H3>Confirm transaction on { device.label } device</H3>
|
||||
<H3>Confirm transaction on { props.device.label } device</H3>
|
||||
<P isSmaller>Details are shown on display</P>
|
||||
</Header>
|
||||
<Content>
|
||||
@ -69,4 +74,9 @@ const ConfirmSignTx = (props: Props) => {
|
||||
);
|
||||
};
|
||||
|
||||
ConfirmSignTx.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
sendForm: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ConfirmSignTx;
|
@ -1,16 +1,27 @@
|
||||
/* @flow */
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import icons from 'config/icons';
|
||||
import colors from 'config/colors';
|
||||
|
||||
import { H2 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import styled from 'styled-components';
|
||||
import Icon from 'components/Icon';
|
||||
import colors from 'config/colors';
|
||||
import icons from 'config/icons';
|
||||
import Button from 'components/Button';
|
||||
import Link from 'components/Link';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
account: $ElementType<$ElementType<BaseProps, 'selectedAccount'>, 'account'>;
|
||||
showAddress: $ElementType<$ElementType<BaseProps, 'receiveActions'>, 'showAddress'>;
|
||||
showUnverifiedAddress: $ElementType<$ElementType<BaseProps, 'receiveActions'>, 'showUnverifiedAddress'>;
|
||||
onCancel: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onCancel'>;
|
||||
}
|
||||
|
||||
const StyledLink = styled(Link)`
|
||||
position: absolute;
|
||||
@ -57,24 +68,20 @@ class ConfirmUnverifiedAddress extends PureComponent<Props> {
|
||||
}
|
||||
|
||||
verifyAddress() {
|
||||
const { account } = this.props.selectedAccount;
|
||||
const { account, onCancel, showAddress } = this.props;
|
||||
if (!account) return;
|
||||
this.props.modalActions.onCancel();
|
||||
this.props.receiveActions.showAddress(account.addressPath);
|
||||
onCancel();
|
||||
showAddress(account.addressPath);
|
||||
}
|
||||
|
||||
showUnverifiedAddress() {
|
||||
this.props.modalActions.onCancel();
|
||||
this.props.receiveActions.showUnverifiedAddress();
|
||||
const { onCancel, showUnverifiedAddress } = this.props;
|
||||
onCancel();
|
||||
showUnverifiedAddress();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
const { device } = this.props.modal;
|
||||
|
||||
const {
|
||||
onCancel,
|
||||
} = this.props.modalActions;
|
||||
const { device, account, onCancel } = this.props;
|
||||
|
||||
let deviceStatus: string;
|
||||
let claim: string;
|
||||
@ -97,7 +104,7 @@ class ConfirmUnverifiedAddress extends PureComponent<Props> {
|
||||
<H2>{ deviceStatus }</H2>
|
||||
<StyledP isSmaller>To prevent phishing attacks, you should verify the address on your TREZOR first. { claim } to continue with the verification process.</StyledP>
|
||||
<Row>
|
||||
<StyledButton onClick={() => (!this.props.selectedAccount.account ? this.verifyAddress() : 'false')}>Try again</StyledButton>
|
||||
<StyledButton onClick={() => (!account ? this.verifyAddress() : 'false')}>Try again</StyledButton>
|
||||
<StyledButton isWhite onClick={() => this.showUnverifiedAddress()}>Show unverified address</StyledButton>
|
||||
</Row>
|
||||
</Wrapper>
|
||||
@ -105,4 +112,12 @@ class ConfirmUnverifiedAddress extends PureComponent<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
ConfirmUnverifiedAddress.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
account: PropTypes.object.isRequired,
|
||||
showAddress: PropTypes.func.isRequired,
|
||||
showUnverifiedAddress: PropTypes.func.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ConfirmUnverifiedAddress;
|
@ -1,19 +1,30 @@
|
||||
/* @flow */
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import icons from 'config/icons';
|
||||
import colors from 'config/colors';
|
||||
import { FONT_SIZE } from 'config/variables';
|
||||
|
||||
import { H3 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import Button from 'components/Button';
|
||||
import Input from 'components/inputs/Input';
|
||||
import { getDuplicateInstanceNumber } from 'reducers/utils';
|
||||
import { FONT_SIZE } from 'config/variables';
|
||||
import Icon from 'components/Icon';
|
||||
import icons from 'config/icons';
|
||||
import colors from 'config/colors';
|
||||
import Link from 'components/Link';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from 'components/modals/index';
|
||||
import { getDuplicateInstanceNumber } from 'reducers/utils';
|
||||
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
devices: $ElementType<BaseProps, 'devices'>;
|
||||
onDuplicateDevice: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onDuplicateDevice'>;
|
||||
onCancel: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onCancel'>;
|
||||
}
|
||||
|
||||
type State = {
|
||||
defaultName: string;
|
||||
@ -63,17 +74,14 @@ const ErrorMessage = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export default class DuplicateDevice extends PureComponent<Props, State> {
|
||||
class DuplicateDevice extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
if (props.modal.context !== CONTEXT_DEVICE) return;
|
||||
const { device } = props.modal;
|
||||
|
||||
const instance = getDuplicateInstanceNumber(props.devices, device);
|
||||
const instance = getDuplicateInstanceNumber(props.devices, props.device);
|
||||
|
||||
this.state = {
|
||||
defaultName: `${device.label} (${instance.toString()})`,
|
||||
defaultName: `${props.device.label} (${instance.toString()})`,
|
||||
instance,
|
||||
instanceName: null,
|
||||
isUsed: false,
|
||||
@ -115,16 +123,12 @@ export default class DuplicateDevice extends PureComponent<Props, State> {
|
||||
keyboardHandler: (event: KeyboardEvent) => void;
|
||||
|
||||
submit() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return;
|
||||
const extended: Object = { instanceName: this.state.instanceName, instance: this.state.instance };
|
||||
this.props.modalActions.onDuplicateDevice({ ...this.props.modal.device, ...extended });
|
||||
this.props.onDuplicateDevice({ ...this.props.device, ...extended });
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
|
||||
const { device } = this.props.modal;
|
||||
const { onCancel } = this.props.modalActions;
|
||||
const { device, onCancel } = this.props;
|
||||
const {
|
||||
defaultName,
|
||||
instanceName,
|
||||
@ -168,4 +172,13 @@ export default class DuplicateDevice extends PureComponent<Props, State> {
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DuplicateDevice.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
devices: PropTypes.array.isRequired,
|
||||
onDuplicateDevice: PropTypes.func.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default DuplicateDevice;
|
@ -1,13 +1,21 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { H3 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import Button from 'components/Button';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
onForgetSingleDevice: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onForgetSingleDevice'>;
|
||||
onCancel: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onCancel'>;
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
width: 360px;
|
||||
@ -48,25 +56,27 @@ class ForgetDevice extends PureComponent<Props> {
|
||||
keyboardHandler: (event: KeyboardEvent) => void;
|
||||
|
||||
forget() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return;
|
||||
this.props.modalActions.onForgetSingleDevice(this.props.modal.device);
|
||||
this.props.onForgetSingleDevice(this.props.device);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
const { device } = this.props.modal;
|
||||
const { onCancel } = this.props.modalActions;
|
||||
return (
|
||||
<Wrapper>
|
||||
<H3>Forget { device.instanceLabel }?</H3>
|
||||
<H3>Forget { this.props.device.instanceLabel }?</H3>
|
||||
<StyledP isSmaller>Forgetting only removes the device from the list on the left, your coins are still safe and you can access them by reconnecting your TREZOR again.</StyledP>
|
||||
<Row>
|
||||
<StyledButton onClick={() => this.forget()}>Forget</StyledButton>
|
||||
<StyledButton isWhite onClick={onCancel}>Don't forget</StyledButton>
|
||||
<StyledButton isWhite onClick={this.props.onCancel}>Don't forget</StyledButton>
|
||||
</Row>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ForgetDevice.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
onForgetSingleDevice: PropTypes.func.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default ForgetDevice;
|
@ -1,13 +1,22 @@
|
||||
/* @flow */
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { H3 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import Loader from 'components/Loader';
|
||||
import Button from 'components/Button';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
instances: ?Array<TrezorDevice>;
|
||||
onRememberDevice: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onRememberDevice'>;
|
||||
onForgetDevice: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onForgetDevice'>;
|
||||
}
|
||||
|
||||
type State = {
|
||||
countdown: number;
|
||||
@ -48,7 +57,7 @@ const StyledLoader = styled(Loader)`
|
||||
left: 200px;
|
||||
`;
|
||||
|
||||
export default class RememberDevice extends PureComponent<Props, State> {
|
||||
class RememberDevice extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
@ -63,8 +72,7 @@ export default class RememberDevice extends PureComponent<Props, State> {
|
||||
// TODO: possible race condition,
|
||||
// device could be already connected but it didn't emit Device.CONNECT event yet
|
||||
window.clearInterval(this.state.ticker);
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return;
|
||||
this.props.modalActions.onForgetDevice(this.props.modal.device);
|
||||
this.props.onForgetDevice(this.props.device);
|
||||
} else {
|
||||
this.setState(previousState => ({
|
||||
countdown: previousState.countdown - 1,
|
||||
@ -98,14 +106,11 @@ export default class RememberDevice extends PureComponent<Props, State> {
|
||||
keyboardHandler: (event: KeyboardEvent) => void;
|
||||
|
||||
forget() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return;
|
||||
this.props.modalActions.onForgetDevice(this.props.modal.device);
|
||||
this.props.onForgetDevice(this.props.device);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
const { device, instances } = this.props.modal;
|
||||
const { onRememberDevice } = this.props.modalActions;
|
||||
const { device, instances, onRememberDevice } = this.props;
|
||||
|
||||
let { label } = device;
|
||||
const devicePlural: string = instances && instances.length > 1 ? 'devices or to remember them' : 'device or to remember it';
|
||||
@ -143,4 +148,13 @@ export default class RememberDevice extends PureComponent<Props, State> {
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RememberDevice.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
instances: PropTypes.array.isRequired,
|
||||
onRememberDevice: PropTypes.func.isRequired,
|
||||
onForgetDevice: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default RememberDevice;
|
@ -1,19 +1,28 @@
|
||||
/* @flow */
|
||||
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled, { css } from 'styled-components';
|
||||
|
||||
import icons from 'config/icons';
|
||||
import colors from 'config/colors';
|
||||
|
||||
import { H3 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import Button from 'components/Button';
|
||||
import Tooltip from 'components/Tooltip';
|
||||
import Icon from 'components/Icon';
|
||||
import Link from 'components/Link';
|
||||
import colors from 'config/colors';
|
||||
import icons from 'config/icons';
|
||||
import WalletTypeIcon from 'components/images/WalletType';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from 'components/modals/index';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
onWalletTypeRequest: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onWalletTypeRequest'>;
|
||||
onCancel: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onCancel'>;
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
width: 360px;
|
||||
@ -89,15 +98,11 @@ class WalletType extends PureComponent<Props> {
|
||||
keyboardHandler: (event: KeyboardEvent) => void;
|
||||
|
||||
changeType(hidden: boolean, state: ?string) {
|
||||
const { modal } = this.props;
|
||||
if (modal.context !== CONTEXT_DEVICE) return;
|
||||
this.props.modalActions.onWalletTypeRequest(modal.device, hidden, state);
|
||||
this.props.onWalletTypeRequest(this.props.device, hidden, state);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
const { device } = this.props.modal;
|
||||
const { onCancel } = this.props.modalActions;
|
||||
const { device, onCancel } = this.props;
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
@ -110,7 +115,7 @@ class WalletType extends PureComponent<Props> {
|
||||
/>
|
||||
</StyledLink>
|
||||
)}
|
||||
<StyledHeading>Change wallet type for { device.instanceLabel }</StyledHeading>
|
||||
<StyledHeading>{ device.state ? 'Change' : 'Select' } wallet type for { device.instanceLabel }</StyledHeading>
|
||||
<Content isTop>
|
||||
<Header>
|
||||
<WalletTypeIcon type="standard" size={32} color={colors.TEXT_PRIMARY} />
|
||||
@ -148,4 +153,10 @@ class WalletType extends PureComponent<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
WalletType.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
onWalletTypeRequest: PropTypes.func.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default WalletType;
|
@ -11,7 +11,11 @@ import Link from 'components/Link';
|
||||
import { H3 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
|
||||
import type { Props } from 'components/modals/index';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
onCancel: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onCancel'>;
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
width: 360px;
|
||||
@ -26,24 +30,21 @@ const StyledLink = styled(Link)`
|
||||
top: 10px;
|
||||
`;
|
||||
|
||||
const Confirmation = (props: Props) => {
|
||||
const { onCancel } = props.modalActions;
|
||||
return (
|
||||
<Wrapper>
|
||||
<StyledLink onClick={onCancel}>
|
||||
<Icon
|
||||
size={20}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
icon={icons.CLOSE}
|
||||
/>
|
||||
</StyledLink>
|
||||
<Header>
|
||||
<Icon icon={icons.T1} size={60} color={colors.TEXT_SECONDARY} />
|
||||
<H3>NEM Wallet</H3>
|
||||
<P isSmaller>If you enter a wrong passphrase, you will not unlock the desired hidden wallet.</P>
|
||||
</Header>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
const Confirmation = (props: Props) => (
|
||||
<Wrapper>
|
||||
<StyledLink onClick={props.onCancel}>
|
||||
<Icon
|
||||
size={20}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
icon={icons.CLOSE}
|
||||
/>
|
||||
</StyledLink>
|
||||
<Header>
|
||||
<Icon icon={icons.T1} size={60} color={colors.TEXT_SECONDARY} />
|
||||
<H3>NEM Wallet</H3>
|
||||
<P isSmaller>If you enter a wrong passphrase, you will not unlock the desired hidden wallet.</P>
|
||||
</Header>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
export default Confirmation;
|
@ -1,67 +1,39 @@
|
||||
/* @flow */
|
||||
|
||||
import * as React from 'react';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
import colors from 'config/colors';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import colors from 'config/colors';
|
||||
|
||||
import { UI } from 'trezor-connect';
|
||||
|
||||
import ModalActions from 'actions/ModalActions';
|
||||
import ReceiveActions from 'actions/ReceiveActions';
|
||||
|
||||
import * as MODAL from 'actions/constants/modal';
|
||||
import * as RECEIVE from 'actions/constants/receive';
|
||||
import * as CONNECT from 'actions/constants/TrezorConnect';
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from 'flowtype';
|
||||
|
||||
// device context
|
||||
import Pin from 'components/modals/pin/Pin';
|
||||
import InvalidPin from 'components/modals/pin/Invalid';
|
||||
|
||||
import Passphrase from 'components/modals/passphrase/Passphrase';
|
||||
import PassphraseType from 'components/modals/passphrase/Type';
|
||||
|
||||
import ConfirmSignTx from 'components/modals/confirm/SignTx';
|
||||
import ConfirmUnverifiedAddress from 'components/modals/confirm/UnverifiedAddress';
|
||||
|
||||
import ForgetDevice from 'components/modals/device/Forget';
|
||||
import RememberDevice from 'components/modals/device/Remember';
|
||||
import DuplicateDevice from 'components/modals/device/Duplicate';
|
||||
import WalletType from 'components/modals/device/WalletType';
|
||||
|
||||
// external context
|
||||
import NemWallet from 'components/modals/external/NemWallet';
|
||||
|
||||
type OwnProps = { }
|
||||
|
||||
type StateProps = {
|
||||
modal: $ElementType<State, 'modal'>,
|
||||
accounts: $ElementType<State, 'accounts'>,
|
||||
devices: $ElementType<State, 'devices'>,
|
||||
connect: $ElementType<State, 'connect'>,
|
||||
selectedAccount: $ElementType<State, 'selectedAccount'>,
|
||||
sendForm: $ElementType<State, 'sendForm'>,
|
||||
receive: $ElementType<State, 'receive'>,
|
||||
localStorage: $ElementType<State, 'localStorage'>,
|
||||
wallet: $ElementType<State, 'wallet'>,
|
||||
}
|
||||
|
||||
type DispatchProps = {
|
||||
modalActions: typeof ModalActions,
|
||||
receiveActions: typeof ReceiveActions,
|
||||
}
|
||||
|
||||
export type Props = StateProps & DispatchProps;
|
||||
import type { Props } from './Container';
|
||||
|
||||
const Fade = (props: { children: React.Node}) => (
|
||||
<CSSTransition
|
||||
{...props}
|
||||
timeout={1000}
|
||||
classNames="fade"
|
||||
>
|
||||
{ props.children }
|
||||
>{ props.children }
|
||||
</CSSTransition>
|
||||
);
|
||||
|
||||
@ -88,85 +60,124 @@ const ModalWindow = styled.div`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
class Modal extends React.PureComponent<Props> {
|
||||
render() {
|
||||
if (this.props.modal.context === MODAL.CONTEXT_NONE) return null;
|
||||
// get modal component with device context
|
||||
const getDeviceContextModal = (props: Props) => {
|
||||
const { modal, modalActions } = props;
|
||||
if (modal.context !== MODAL.CONTEXT_DEVICE) return null;
|
||||
|
||||
const { windowType } = this.props.modal;
|
||||
let component = null;
|
||||
switch (windowType) {
|
||||
case UI.REQUEST_PIN:
|
||||
component = (<Pin {...this.props} />);
|
||||
break;
|
||||
case UI.INVALID_PIN:
|
||||
component = (<InvalidPin {...this.props} />);
|
||||
break;
|
||||
case UI.REQUEST_PASSPHRASE:
|
||||
component = (<Passphrase {...this.props} />);
|
||||
break;
|
||||
case 'ButtonRequest_SignTx':
|
||||
component = (<ConfirmSignTx {...this.props} />);
|
||||
break;
|
||||
case 'ButtonRequest_PassphraseType':
|
||||
component = (<PassphraseType {...this.props} />);
|
||||
break;
|
||||
case RECEIVE.REQUEST_UNVERIFIED:
|
||||
component = (<ConfirmUnverifiedAddress {...this.props} />);
|
||||
break;
|
||||
switch (modal.windowType) {
|
||||
case UI.REQUEST_PIN:
|
||||
return (
|
||||
<Pin
|
||||
device={modal.device}
|
||||
onPinSubmit={modalActions.onPinSubmit}
|
||||
/>);
|
||||
|
||||
case CONNECT.REMEMBER_REQUEST:
|
||||
component = (<RememberDevice {...this.props} />);
|
||||
break;
|
||||
case UI.INVALID_PIN:
|
||||
return <InvalidPin device={modal.device} />;
|
||||
|
||||
case CONNECT.FORGET_REQUEST:
|
||||
component = (<ForgetDevice {...this.props} />);
|
||||
break;
|
||||
case UI.REQUEST_PASSPHRASE:
|
||||
return (
|
||||
<Passphrase
|
||||
device={modal.device}
|
||||
selectedDevice={props.wallet.selectedDevice}
|
||||
onPassphraseSubmit={modalActions.onPassphraseSubmit}
|
||||
/>);
|
||||
|
||||
case CONNECT.TRY_TO_DUPLICATE:
|
||||
component = (<DuplicateDevice {...this.props} />);
|
||||
break;
|
||||
case 'ButtonRequest_PassphraseType':
|
||||
return <PassphraseType device={modal.device} />;
|
||||
|
||||
case CONNECT.REQUEST_WALLET_TYPE:
|
||||
component = (<WalletType {...this.props} />);
|
||||
break;
|
||||
case 'ButtonRequest_SignTx':
|
||||
return <ConfirmSignTx device={modal.device} sendForm={props.sendForm} />;
|
||||
|
||||
case 'xem':
|
||||
component = (<NemWallet {...this.props} />);
|
||||
break;
|
||||
default:
|
||||
component = null;
|
||||
}
|
||||
case RECEIVE.REQUEST_UNVERIFIED:
|
||||
return (
|
||||
<ConfirmUnverifiedAddress
|
||||
device={modal.device}
|
||||
account={props.selectedAccount.account}
|
||||
onCancel={modalActions.onCancel}
|
||||
showAddress={props.receiveActions.showAddress}
|
||||
showUnverifiedAddress={props.receiveActions.showUnverifiedAddress}
|
||||
/>);
|
||||
|
||||
return (
|
||||
<Fade key="1">
|
||||
<ModalContainer>
|
||||
<ModalWindow>
|
||||
{ component }
|
||||
</ModalWindow>
|
||||
</ModalContainer>
|
||||
</Fade>
|
||||
);
|
||||
case CONNECT.REMEMBER_REQUEST:
|
||||
return (
|
||||
<RememberDevice
|
||||
device={modal.device}
|
||||
instances={modal.instances}
|
||||
onRememberDevice={modalActions.onRememberDevice}
|
||||
onForgetDevice={modalActions.onForgetDevice}
|
||||
/>);
|
||||
|
||||
case CONNECT.FORGET_REQUEST:
|
||||
return (
|
||||
<ForgetDevice
|
||||
device={modal.device}
|
||||
onForgetSingleDevice={modalActions.onForgetSingleDevice}
|
||||
onCancel={modalActions.onCancel}
|
||||
/>);
|
||||
|
||||
case CONNECT.TRY_TO_DUPLICATE:
|
||||
return (
|
||||
<DuplicateDevice
|
||||
device={modal.device}
|
||||
devices={props.devices}
|
||||
onDuplicateDevice={modalActions.onDuplicateDevice}
|
||||
onCancel={modalActions.onCancel}
|
||||
/>);
|
||||
|
||||
case CONNECT.REQUEST_WALLET_TYPE:
|
||||
return (
|
||||
<WalletType
|
||||
device={modal.device}
|
||||
onWalletTypeRequest={modalActions.onWalletTypeRequest}
|
||||
onCancel={modalActions.onCancel}
|
||||
/>);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State): StateProps => ({
|
||||
modal: state.modal,
|
||||
accounts: state.accounts,
|
||||
devices: state.devices,
|
||||
connect: state.connect,
|
||||
selectedAccount: state.selectedAccount,
|
||||
sendForm: state.sendForm,
|
||||
receive: state.receive,
|
||||
localStorage: state.localStorage,
|
||||
wallet: state.wallet,
|
||||
});
|
||||
// get modal component with external context
|
||||
const getExternalContextModal = (props: Props) => {
|
||||
const { modal, modalActions } = props;
|
||||
if (modal.context !== MODAL.CONTEXT_EXTERNAL_WALLET) return null;
|
||||
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => ({
|
||||
modalActions: bindActionCreators(ModalActions, dispatch),
|
||||
receiveActions: bindActionCreators(ReceiveActions, dispatch),
|
||||
});
|
||||
switch (modal.windowType) {
|
||||
case 'xem':
|
||||
return (<NemWallet onCancel={modalActions.onCancel} />);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// export default connect(mapStateToProps, mapDispatchToProps)(Modal);
|
||||
export default withRouter(
|
||||
connect(mapStateToProps, mapDispatchToProps)(Modal),
|
||||
);
|
||||
// modal container component
|
||||
const Modal = (props: Props) => {
|
||||
const { modal } = props;
|
||||
if (modal.context === MODAL.CONTEXT_NONE) return null;
|
||||
|
||||
let component = null;
|
||||
switch (modal.context) {
|
||||
case MODAL.CONTEXT_DEVICE:
|
||||
component = getDeviceContextModal(props);
|
||||
break;
|
||||
case MODAL.CONTEXT_EXTERNAL_WALLET:
|
||||
component = getExternalContextModal(props);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fade key="modal-fade">
|
||||
<ModalContainer>
|
||||
<ModalWindow>
|
||||
{ component }
|
||||
</ModalWindow>
|
||||
</ModalContainer>
|
||||
</Fade>
|
||||
);
|
||||
};
|
||||
|
||||
export default Modal;
|
||||
|
@ -1,16 +1,25 @@
|
||||
/* @flow */
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import colors from 'config/colors';
|
||||
import { FONT_SIZE, TRANSITION } from 'config/variables';
|
||||
|
||||
import { H2 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import Checkbox from 'components/Checkbox';
|
||||
import Button from 'components/Button';
|
||||
import Input from 'components/inputs/Input';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
selectedDevice: ?TrezorDevice;
|
||||
onPassphraseSubmit: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onPassphraseSubmit'>;
|
||||
}
|
||||
|
||||
type State = {
|
||||
deviceLabel: string,
|
||||
@ -80,13 +89,10 @@ const LinkButton = styled(Button)`
|
||||
class Passphrase extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
if (props.modal.context !== CONTEXT_DEVICE) return;
|
||||
const { device } = props.modal;
|
||||
const { device, selectedDevice } = props;
|
||||
|
||||
// Check if this device is already known
|
||||
// if device is already known then only one input is presented
|
||||
const { selectedDevice } = props.wallet;
|
||||
let deviceLabel = device.label;
|
||||
let shouldShowSingleInput = false;
|
||||
if (selectedDevice && selectedDevice.path === device.path) {
|
||||
@ -104,8 +110,6 @@ class Passphrase extends PureComponent<Props, State> {
|
||||
};
|
||||
}
|
||||
|
||||
state: State;
|
||||
|
||||
componentDidMount() {
|
||||
this.passphraseInput.focus();
|
||||
|
||||
@ -179,7 +183,7 @@ class Passphrase extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
submitPassphrase(shouldLeavePassphraseBlank: boolean = false) {
|
||||
const { onPassphraseSubmit } = this.props.modalActions;
|
||||
const { onPassphraseSubmit } = this.props;
|
||||
const passphrase = this.state.passphraseInputValue;
|
||||
|
||||
// Reset state so same passphrase isn't filled when the modal will be visible again
|
||||
@ -203,8 +207,6 @@ class Passphrase extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<H2>Enter {this.state.deviceLabel} passphrase</H2>
|
||||
@ -273,4 +275,10 @@ class Passphrase extends PureComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
Passphrase.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
selectedDevice: PropTypes.object.isRequired,
|
||||
onPassphraseSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default Passphrase;
|
@ -1,15 +1,21 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import Icon from 'components/Icon';
|
||||
import colors from 'config/colors';
|
||||
import icons from 'config/icons';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import icons from 'config/icons';
|
||||
import colors from 'config/colors';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import { H3 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from 'components/modals/index';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
width: 360px;
|
||||
@ -18,19 +24,18 @@ const Wrapper = styled.div`
|
||||
|
||||
const Header = styled.div``;
|
||||
|
||||
const Confirmation = (props: Props) => {
|
||||
if (props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
const { device } = props.modal;
|
||||
const PassphraseType = (props: Props) => (
|
||||
<Wrapper>
|
||||
<Header>
|
||||
<Icon icon={icons.T1} size={60} color={colors.TEXT_SECONDARY} />
|
||||
<H3>Complete the action on { props.device.label } device</H3>
|
||||
<P isSmaller>If you enter a wrong passphrase, you will not unlock the desired hidden wallet.</P>
|
||||
</Header>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Header>
|
||||
<Icon icon={icons.T1} size={60} color={colors.TEXT_SECONDARY} />
|
||||
<H3>Complete the action on { device.label } device</H3>
|
||||
<P isSmaller>If you enter a wrong passphrase, you will not unlock the desired hidden wallet.</P>
|
||||
</Header>
|
||||
</Wrapper>
|
||||
);
|
||||
PassphraseType.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default Confirmation;
|
||||
export default PassphraseType;
|
@ -1,27 +1,31 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { H3 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
padding: 24px 48px;
|
||||
`;
|
||||
|
||||
const InvalidPin = (props: Props) => {
|
||||
if (props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
const InvalidPin = (props: Props) => (
|
||||
<Wrapper>
|
||||
<H3>Entered PIN for { props.device.label } is not correct</H3>
|
||||
<P isSmaller>Retrying...</P>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
const { device } = props.modal;
|
||||
return (
|
||||
<Wrapper>
|
||||
<H3>Entered PIN for { device.label } is not correct</H3>
|
||||
<P isSmaller>Retrying...</P>
|
||||
</Wrapper>
|
||||
);
|
||||
InvalidPin.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default InvalidPin;
|
@ -1,15 +1,24 @@
|
||||
/* @flow */
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import P from 'components/Paragraph';
|
||||
import { H2 } from 'components/Heading';
|
||||
import React, { PureComponent } from 'react';
|
||||
import Link from 'components/Link';
|
||||
import styled from 'styled-components';
|
||||
import Button from 'components/Button';
|
||||
import { CONTEXT_DEVICE } from 'actions/constants/modal';
|
||||
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
|
||||
import PinButton from './components/Button';
|
||||
import PinInput from './components/Input';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice;
|
||||
onPinSubmit: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onPinSubmit'>;
|
||||
}
|
||||
|
||||
type State = {
|
||||
pin: string;
|
||||
@ -75,7 +84,7 @@ class Pin extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
keyboardHandler(event: KeyboardEvent): void {
|
||||
const { onPinSubmit } = this.props.modalActions;
|
||||
const { onPinSubmit } = this.props;
|
||||
const { pin } = this.state;
|
||||
|
||||
event.preventDefault();
|
||||
@ -133,9 +142,7 @@ class Pin extends PureComponent<Props, State> {
|
||||
keyboardHandler: (event: KeyboardEvent) => void;
|
||||
|
||||
render() {
|
||||
if (this.props.modal.context !== CONTEXT_DEVICE) return null;
|
||||
const { onPinSubmit } = this.props.modalActions;
|
||||
const { device } = this.props.modal;
|
||||
const { device, onPinSubmit } = this.props;
|
||||
const { pin } = this.state;
|
||||
return (
|
||||
<Wrapper>
|
||||
@ -174,4 +181,9 @@ class Pin extends PureComponent<Props, State> {
|
||||
}
|
||||
}
|
||||
|
||||
Pin.propTypes = {
|
||||
device: PropTypes.object.isRequired,
|
||||
onPinSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default Pin;
|
@ -11,7 +11,7 @@ import type { State } from 'flowtype';
|
||||
|
||||
import Header from 'components/Header';
|
||||
import Footer from 'components/Footer';
|
||||
import ModalContainer from 'components/modals';
|
||||
import ModalContainer from 'components/modals/Container';
|
||||
import AppNotifications from 'components/notifications/App';
|
||||
import ContextNotifications from 'components/notifications/Context';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user