1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-11-16 05:19:12 +00:00
trezor-wallet/src/components/modals/QrModal/index.js

180 lines
4.9 KiB
JavaScript
Raw Normal View History

2019-01-17 16:12:12 +00:00
/* @flow */
2019-02-22 18:33:11 +00:00
import React, { Component } from 'react';
2019-01-17 16:12:12 +00:00
import PropTypes from 'prop-types';
import QrReader from 'react-qr-reader';
import styled from 'styled-components';
2019-02-22 18:33:11 +00:00
import { FormattedMessage, injectIntl } from 'react-intl';
2019-03-18 16:41:51 +00:00
import { Link, Icon, P, H5, icons, colors } from 'trezor-ui-components';
2019-01-17 16:12:12 +00:00
import { parseUri } from 'utils/cryptoUriParser';
import type { parsedURI } from 'utils/cryptoUriParser';
2019-02-22 18:33:11 +00:00
import l10nMessages from './index.messages';
2019-01-17 16:12:12 +00:00
import type { Props as BaseProps } from '../Container';
const Wrapper = styled.div`
2019-01-17 23:53:30 +00:00
width: 90vw;
max-width: 450px;
2019-01-19 19:51:43 +00:00
padding: 30px 0px;
2019-01-17 16:12:12 +00:00
`;
const Padding = styled.div`
padding: 0px 48px;
`;
const CloseLink = styled(Link)`
position: absolute;
right: 15px;
top: 15px;
`;
const CameraPlaceholder = styled(P)`
text-align: center;
padding: 10px 0;
`;
2019-02-20 15:35:28 +00:00
const Error = styled.div`
2019-01-17 16:12:12 +00:00
padding: 10px 0;
2019-02-20 15:35:28 +00:00
`;
const ErrorTitle = styled(P)`
text-align: center;
2019-01-17 16:12:12 +00:00
color: ${colors.ERROR_PRIMARY};
`;
2019-02-20 15:35:28 +00:00
const ErrorMessage = styled.span`
text-align: center;
color: ${colors.TEXT_PRIMARY};
`;
2019-01-17 16:12:12 +00:00
const StyledQrReader = styled(QrReader)`
padding: 10px 0;
`;
// TODO fix types
type Props = {
onScan: (data: parsedURI) => any,
onError?: (error: any) => any,
2019-02-22 18:33:11 +00:00
onCancel?: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onCancel'>,
intl: any,
2019-03-04 12:33:02 +00:00
};
2019-01-17 16:12:12 +00:00
type State = {
readerLoaded: boolean,
error: any,
};
2019-02-22 18:33:11 +00:00
class QrModal extends Component<Props, State> {
2019-01-17 16:12:12 +00:00
constructor(props: Props) {
super(props);
this.state = {
readerLoaded: false,
error: null,
};
}
onLoad = () => {
this.setState({
readerLoaded: true,
});
2019-03-04 12:33:02 +00:00
};
2019-01-17 16:12:12 +00:00
handleScan = (data: string) => {
if (data) {
try {
const parsedUri = parseUri(data);
if (parsedUri) {
this.props.onScan(parsedUri);
// reset error
this.setState({
error: null,
});
// close window
this.handleCancel();
}
} catch (error) {
this.handleError(error);
}
}
2019-03-04 12:33:02 +00:00
};
2019-01-17 16:12:12 +00:00
handleError = (err: any) => {
2019-02-20 15:35:28 +00:00
// log thrown error
console.error(err);
2019-01-17 16:12:12 +00:00
if (this.props.onError) {
this.props.onError(err);
}
2019-02-20 15:35:28 +00:00
2019-03-04 12:33:02 +00:00
if (
err.name === 'NotAllowedError' ||
err.name === 'PermissionDeniedError' ||
err.name === 'NotReadableError' ||
err.name === 'TrackStartError'
) {
2019-02-20 15:35:28 +00:00
this.setState({
2019-02-22 18:33:11 +00:00
error: this.props.intl.formatMessage(l10nMessages.TR_CAMERA_PERMISSION_DENIED),
2019-02-20 15:35:28 +00:00
});
} else if (err.name === 'NotFoundError' || err.name === 'DevicesNotFoundError') {
this.setState({
2019-02-22 18:33:11 +00:00
error: this.props.intl.formatMessage(l10nMessages.TR_CAMERA_NOT_RECOGNIZED),
2019-02-20 15:35:28 +00:00
});
} else {
this.setState({
2019-02-22 18:33:11 +00:00
error: this.props.intl.formatMessage(l10nMessages.TR_UNKOWN_ERROR_SEE_CONSOLE),
2019-02-20 15:35:28 +00:00
});
}
2019-03-04 12:33:02 +00:00
};
2019-01-17 16:12:12 +00:00
handleCancel = () => {
if (this.props.onCancel) {
this.props.onCancel();
}
2019-03-04 12:33:02 +00:00
};
2019-01-17 16:12:12 +00:00
render() {
return (
<Wrapper>
<CloseLink onClick={this.handleCancel}>
2019-03-25 10:53:23 +00:00
<Icon size={12} color={colors.TEXT_SECONDARY} icon={icons.CLOSE} />
2019-01-17 16:12:12 +00:00
</CloseLink>
<Padding>
2019-03-18 16:41:51 +00:00
<H5>
2019-03-04 12:33:02 +00:00
<FormattedMessage {...l10nMessages.TR_SCAN_QR_CODE} />
2019-03-18 16:41:51 +00:00
</H5>
2019-03-04 12:33:02 +00:00
{!this.state.readerLoaded && !this.state.error && (
<CameraPlaceholder>
<FormattedMessage {...l10nMessages.TR_WAITING_FOR_CAMERA} />
</CameraPlaceholder>
)}
2019-01-17 16:12:12 +00:00
{this.state.error && (
<Error>
2019-03-04 12:33:02 +00:00
<ErrorTitle>
<FormattedMessage {...l10nMessages.TR_OOPS_SOMETHING_WENT_WRONG} />
</ErrorTitle>
2019-02-20 15:35:28 +00:00
<ErrorMessage>{this.state.error.toString()}</ErrorMessage>
2019-01-17 16:12:12 +00:00
</Error>
)}
</Padding>
2019-02-20 15:35:28 +00:00
{!this.state.error && (
<StyledQrReader
delay={500}
onError={this.handleError}
onScan={this.handleScan}
onLoad={this.onLoad}
style={{ width: '100%' }}
showViewFinder={false}
/>
)}
2019-01-17 16:12:12 +00:00
</Wrapper>
);
}
}
QrModal.propTypes = {
onScan: PropTypes.func.isRequired,
onError: PropTypes.func,
onCancel: PropTypes.func,
2019-02-22 18:33:11 +00:00
intl: PropTypes.any,
2019-01-17 16:12:12 +00:00
};
2019-02-22 18:33:11 +00:00
export default injectIntl(QrModal);