mirror of https://github.com/trezor/trezor-wallet
parent
449b2923fd
commit
651242ffcf
@ -0,0 +1,73 @@
|
||||
/* @flow */
|
||||
import * as React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import Header from 'components/Header';
|
||||
import Footer from 'components/Footer';
|
||||
import Log from 'components/Log';
|
||||
import Loader from 'components/Loader';
|
||||
import ContextNotifications from 'components/notifications/Context';
|
||||
import colors from 'config/colors';
|
||||
|
||||
import InitializationError from '../InitializationError';
|
||||
|
||||
type Props = {
|
||||
loading?: boolean;
|
||||
error?: ?string;
|
||||
children?: React.Node;
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
min-height: 100%;
|
||||
min-width: 720px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
text-align: center;
|
||||
background: ${colors.LANDING};
|
||||
`;
|
||||
|
||||
const LandingContent = styled.div`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const LandingLoader = styled(Loader)`
|
||||
margin: auto;
|
||||
`;
|
||||
|
||||
const LandingWrapper = (props: Props) => (
|
||||
<Wrapper>
|
||||
{props.loading && <LandingLoader text="Loading" size={100} />}
|
||||
{!props.loading && (
|
||||
<React.Fragment>
|
||||
<Header />
|
||||
<ContextNotifications />
|
||||
{props.error && <InitializationError error={props.error} />}
|
||||
<Log />
|
||||
{!props.error && (
|
||||
<LandingContent>
|
||||
{ props.children }
|
||||
</LandingContent>
|
||||
)}
|
||||
<Footer />
|
||||
</React.Fragment>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
LandingWrapper.propTypes = {
|
||||
loading: PropTypes.bool,
|
||||
error: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
};
|
||||
|
||||
LandingWrapper.defaultProps = {
|
||||
loading: false,
|
||||
error: null,
|
||||
};
|
||||
|
||||
export default LandingWrapper;
|
@ -1,158 +0,0 @@
|
||||
/* @flow */
|
||||
import React from 'react';
|
||||
import CaseImage from 'images/case.png';
|
||||
import styled from 'styled-components';
|
||||
import Header from 'components/Header';
|
||||
import Footer from 'components/Footer';
|
||||
import Log from 'components/Log';
|
||||
import Link from 'components/Link';
|
||||
import Loader from 'components/Loader';
|
||||
import Notification from 'components/Notification';
|
||||
import ContextNotifications from 'components/notifications/Context';
|
||||
import colors from 'config/colors';
|
||||
import P from 'components/Paragraph';
|
||||
import { H2 } from 'components/Heading';
|
||||
import { isWebUSB } from 'utils/device';
|
||||
import { FONT_SIZE } from 'config/variables';
|
||||
|
||||
import InitializationError from './components/InitializationError';
|
||||
import BrowserNotSupported from './components/BrowserNotSupported';
|
||||
import ConnectDevice from './components/ConnectDevice';
|
||||
import InstallBridge from './components/InstallBridge';
|
||||
|
||||
import type { Props } from './Container';
|
||||
|
||||
const LandingWrapper = styled.div`
|
||||
min-height: 100%;
|
||||
min-width: 720px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
text-align: center;
|
||||
background: ${colors.LANDING};
|
||||
`;
|
||||
|
||||
const LandingContent = styled.div`
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const LandingImage = styled.img`
|
||||
width: 777px;
|
||||
min-height: 500px;
|
||||
margin: auto;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center 0px;
|
||||
background-size: contain;
|
||||
`;
|
||||
|
||||
const TitleWrapper = styled.div`
|
||||
margin-top: 60px;
|
||||
`;
|
||||
|
||||
const LandingFooterWrapper = styled.div`
|
||||
margin-bottom: 32px;
|
||||
`;
|
||||
|
||||
const LandingFooterTextWrapper = styled.span`
|
||||
margin-right: 4px;
|
||||
`;
|
||||
|
||||
const LandingLoader = styled(Loader)`
|
||||
margin: auto;
|
||||
`;
|
||||
|
||||
const StyledLink = styled(Link)`
|
||||
font-size: ${FONT_SIZE.BASE};
|
||||
`;
|
||||
|
||||
export default (props: Props) => {
|
||||
const { devices } = props;
|
||||
const { browserState, transport } = props.connect;
|
||||
const localStorageError = props.localStorage.error;
|
||||
const connectError = props.connect.error;
|
||||
|
||||
const bridgeRoute: boolean = props.router.location.state.hasOwnProperty('bridge');
|
||||
const deviceLabel = props.wallet.disconnectRequest ? props.wallet.disconnectRequest.label : '';
|
||||
|
||||
const shouldShowInitializationError = connectError && !props.connect.initialized;
|
||||
const shouldShowInstallBridge = props.connect.initialized && (connectError || bridgeRoute);
|
||||
const shouldShowConnectDevice = props.wallet.ready && devices.length < 1;
|
||||
const shouldShowDisconnectDevice = !!props.wallet.disconnectRequest;
|
||||
const shouldShowUnsupportedBrowser = browserState.supported === false;
|
||||
|
||||
const isLoading = !shouldShowInitializationError && !shouldShowInstallBridge && !shouldShowConnectDevice && !shouldShowUnsupportedBrowser && !localStorageError;
|
||||
|
||||
return (
|
||||
<LandingWrapper>
|
||||
{isLoading && <LandingLoader text="Loading" size={100} />}
|
||||
{!isLoading && (
|
||||
<React.Fragment>
|
||||
<Header />
|
||||
{localStorageError && (
|
||||
<Notification
|
||||
title="Initialization error"
|
||||
message="Config files are missing"
|
||||
type="error"
|
||||
/>
|
||||
)}
|
||||
<ContextNotifications />
|
||||
{shouldShowInitializationError && <InitializationError error={connectError} />}
|
||||
<Log />
|
||||
<LandingContent>
|
||||
{shouldShowUnsupportedBrowser && <BrowserNotSupported />}
|
||||
{shouldShowInstallBridge && <InstallBridge selectFirstAvailableDevice={props.selectFirstAvailableDevice} transport={transport} />}
|
||||
|
||||
{!shouldShowInstallBridge && (shouldShowConnectDevice || shouldShowDisconnectDevice) && (
|
||||
<div>
|
||||
<TitleWrapper>
|
||||
<H2 claim>The private bank in your hands.</H2>
|
||||
<P>TREZOR Wallet is an easy-to-use interface for your TREZOR.</P>
|
||||
<P>TREZOR Wallet allows you to easily control your funds, manage your balance and initiate transfers.</P>
|
||||
</TitleWrapper>
|
||||
|
||||
<ConnectDevice
|
||||
deviceLabel={deviceLabel}
|
||||
showWebUsb={isWebUSB(transport)}
|
||||
showDisconnect={shouldShowDisconnectDevice}
|
||||
/>
|
||||
|
||||
<LandingImage src={CaseImage} />
|
||||
|
||||
{shouldShowConnectDevice && (
|
||||
<LandingFooterWrapper>
|
||||
{isWebUSB(transport) && (
|
||||
<P>
|
||||
<LandingFooterTextWrapper>Device not recognized?</LandingFooterTextWrapper>
|
||||
<StyledLink
|
||||
to="/bridge"
|
||||
isGreen
|
||||
>Try installing the TREZOR Bridge.
|
||||
</StyledLink>
|
||||
</P>
|
||||
)}
|
||||
<P>
|
||||
<LandingFooterTextWrapper>
|
||||
Don't have TREZOR?
|
||||
</LandingFooterTextWrapper>
|
||||
<StyledLink
|
||||
href="https://trezor.io/"
|
||||
isGreen
|
||||
>Get one
|
||||
</StyledLink>
|
||||
</P>
|
||||
</LandingFooterWrapper>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</LandingContent>
|
||||
|
||||
<Footer />
|
||||
</React.Fragment>
|
||||
)}
|
||||
</LandingWrapper>
|
||||
);
|
||||
};
|
@ -0,0 +1,40 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import colors from 'config/colors';
|
||||
import icons from 'config/icons';
|
||||
|
||||
import { H2 } from 'components/Heading';
|
||||
import Icon from 'components/Icon';
|
||||
import Link from 'components/Link';
|
||||
import Button from 'components/Button';
|
||||
import LandingWrapper from 'views/Landing/components/LandingWrapper';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
min-width: 720px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const Import = () => (
|
||||
<LandingWrapper>
|
||||
<Wrapper>
|
||||
<Icon
|
||||
size={60}
|
||||
color={colors.WARNING_PRIMARY}
|
||||
icon={icons.WARNING}
|
||||
/>
|
||||
<H2>Import tool is under construction</H2>
|
||||
<Link to="/">
|
||||
<Button>Take me back</Button>
|
||||
</Link>
|
||||
</Wrapper>
|
||||
</LandingWrapper>
|
||||
);
|
||||
|
||||
export default Import;
|
@ -0,0 +1,34 @@
|
||||
/* @flow */
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import * as RouterActions from 'actions/RouterActions';
|
||||
|
||||
import type { MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import type { State, Dispatch } from 'flowtype';
|
||||
import InstallBridge from './index';
|
||||
|
||||
export type StateProps = {
|
||||
transport: $ElementType<$ElementType<State, 'connect'>, 'transport'>,
|
||||
children?: React.Node,
|
||||
}
|
||||
|
||||
type DispatchProps = {
|
||||
selectFirstAvailableDevice: typeof RouterActions.selectFirstAvailableDevice,
|
||||
}
|
||||
|
||||
type OwnProps = {
|
||||
|
||||
}
|
||||
|
||||
export type Props = StateProps & DispatchProps;
|
||||
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State): StateProps => ({
|
||||
transport: state.connect.transport,
|
||||
});
|
||||
|
||||
const mapDispatchToProps: MapDispatchToProps<Dispatch, OwnProps, DispatchProps> = (dispatch: Dispatch): DispatchProps => ({
|
||||
selectFirstAvailableDevice: bindActionCreators(RouterActions.selectFirstAvailableDevice, dispatch),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(InstallBridge);
|
@ -0,0 +1,34 @@
|
||||
/* @flow */
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import type { MapStateToProps } from 'react-redux';
|
||||
import type { State } from 'flowtype';
|
||||
import RootView from './index';
|
||||
|
||||
export type StateProps = {
|
||||
localStorage: $ElementType<State, 'localStorage'>,
|
||||
modal: $ElementType<State, 'modal'>,
|
||||
wallet: $ElementType<State, 'wallet'>,
|
||||
connect: $ElementType<State, 'connect'>,
|
||||
router: $ElementType<State, 'router'>,
|
||||
wallet: $ElementType<State, 'wallet'>,
|
||||
devices: $ElementType<State, 'devices'>,
|
||||
children?: React.Node,
|
||||
}
|
||||
|
||||
type DispatchProps = {};
|
||||
type OwnProps = {};
|
||||
|
||||
export type Props = StateProps & DispatchProps;
|
||||
|
||||
const mapStateToProps: MapStateToProps<State, OwnProps, StateProps> = (state: State): StateProps => ({
|
||||
localStorage: state.localStorage,
|
||||
modal: state.modal,
|
||||
wallet: state.wallet,
|
||||
connect: state.connect,
|
||||
router: state.router,
|
||||
devices: state.devices,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, null)(RootView);
|
@ -0,0 +1,45 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import { isWebUSB } from 'utils/device';
|
||||
|
||||
import LandingWrapper from 'views/Landing/components/LandingWrapper';
|
||||
import BrowserNotSupported from 'views/Landing/components/BrowserNotSupported';
|
||||
import ConnectDevice from 'views/Landing/components/ConnectDevice';
|
||||
import InstallBridge from 'views/Landing/views/InstallBridge/Container';
|
||||
|
||||
import type { Props } from './Container';
|
||||
|
||||
const Root = (props: Props) => {
|
||||
const { initialized, browserState, transport } = props.connect;
|
||||
const { disconnectRequest } = props.wallet;
|
||||
const localStorageError = props.localStorage.error;
|
||||
const connectError = props.connect.error;
|
||||
|
||||
const error = !initialized ? (localStorageError || connectError) : null;
|
||||
const shouldShowUnsupportedBrowser = browserState.supported === false;
|
||||
const shouldShowInstallBridge = initialized && connectError;
|
||||
const shouldShowConnectDevice = props.wallet.ready && props.devices.length < 1;
|
||||
const shouldShowDisconnectDevice = !!disconnectRequest;
|
||||
const isLoading = !error && !shouldShowUnsupportedBrowser && !shouldShowConnectDevice && !shouldShowUnsupportedBrowser;
|
||||
|
||||
const deviceLabel = disconnectRequest ? disconnectRequest.label : '';
|
||||
// corner case: display InstallBridge view on "/" route
|
||||
// it has it's own Container and props
|
||||
if (shouldShowInstallBridge) return <InstallBridge />;
|
||||
|
||||
return (
|
||||
<LandingWrapper loading={isLoading} error={error}>
|
||||
{shouldShowUnsupportedBrowser && <BrowserNotSupported />}
|
||||
{(shouldShowConnectDevice || shouldShowDisconnectDevice) && (
|
||||
<ConnectDevice
|
||||
deviceLabel={deviceLabel}
|
||||
showWebUsb={isWebUSB(transport)}
|
||||
showDisconnect={shouldShowDisconnectDevice}
|
||||
/>
|
||||
)}
|
||||
</LandingWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Root;
|
Loading…
Reference in new issue