mirror of
https://github.com/trezor/trezor-wallet
synced 2025-08-05 13:27:18 +00:00
Merge pull request #155 from trezor/flowtype/notifications
Flowtype/notifications
This commit is contained in:
commit
6dfd941c44
@ -3,4 +3,5 @@ build
|
|||||||
build-devel
|
build-devel
|
||||||
coverage
|
coverage
|
||||||
node_modules
|
node_modules
|
||||||
src/flowtype/npm
|
src/flowtype/npm
|
||||||
|
**/_old/*
|
@ -1,9 +1,24 @@
|
|||||||
import React from 'react';
|
/* @flow */
|
||||||
|
|
||||||
|
import * as 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, FONT_WEIGHT, FONT_SIZE } from 'config/variables';
|
import { TRANSITION, FONT_WEIGHT, FONT_SIZE } from 'config/variables';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: React.Node,
|
||||||
|
className?: string,
|
||||||
|
onClick?: () => any,
|
||||||
|
onMouseEnter?: () => void,
|
||||||
|
onMouseLeave?: () => void,
|
||||||
|
onFocus?: () => void,
|
||||||
|
isDisabled?: boolean,
|
||||||
|
isWhite?: boolean,
|
||||||
|
isWebUsb?: boolean,
|
||||||
|
isTransparent?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -108,8 +123,8 @@ const Wrapper = styled.button`
|
|||||||
|
|
||||||
const Button = ({
|
const Button = ({
|
||||||
children,
|
children,
|
||||||
className,
|
className = '',
|
||||||
onClick = () => { },
|
onClick,
|
||||||
onMouseEnter,
|
onMouseEnter,
|
||||||
onMouseLeave,
|
onMouseLeave,
|
||||||
onFocus,
|
onFocus,
|
||||||
@ -117,7 +132,7 @@ const Button = ({
|
|||||||
isWhite = false,
|
isWhite = false,
|
||||||
isWebUsb = false,
|
isWebUsb = false,
|
||||||
isTransparent = false,
|
isTransparent = false,
|
||||||
}) => {
|
}: Props) => {
|
||||||
const newClassName = isWebUsb ? `${className} trezor-webusb-button` : className;
|
const newClassName = isWebUsb ? `${className} trezor-webusb-button` : className;
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
@ -6,6 +8,12 @@ import Icon from 'components/Icon';
|
|||||||
import icons from 'config/icons';
|
import icons from 'config/icons';
|
||||||
import { FONT_SIZE } from 'config/variables';
|
import { FONT_SIZE } from 'config/variables';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onClick: (event: KeyboardEvent) => void,
|
||||||
|
isChecked: boolean,
|
||||||
|
children: string,
|
||||||
|
}
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -54,10 +62,10 @@ const Label = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
class Checkbox extends PureComponent {
|
class Checkbox extends PureComponent<Props> {
|
||||||
handleKeyboard(e) {
|
handleKeyboard(event: KeyboardEvent) {
|
||||||
if (e.keyCode === 32) {
|
if (event.keyCode === 32) {
|
||||||
this.props.onClick(e);
|
this.props.onClick(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +78,7 @@ class Checkbox extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onKeyUp={e => this.handleKeyboard(e)}
|
onKeyUp={event => this.handleKeyboard(event)}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
<IconWrapper isChecked={isChecked}>
|
<IconWrapper isChecked={isChecked}>
|
||||||
|
@ -11,6 +11,11 @@ import { connect } from 'react-redux';
|
|||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import * as LogActions from 'actions/LogActions';
|
import * as LogActions from 'actions/LogActions';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
opened: boolean,
|
||||||
|
toggle: () => any,
|
||||||
|
}
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -30,7 +35,7 @@ const Copy = styled.div`
|
|||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Footer = ({ opened, toggle }) => (
|
const Footer = ({ opened, toggle }: Props) => (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Copy title={window.COMMITHASH}>© {getYear(new Date())}</Copy>
|
<Copy title={window.COMMITHASH}>© {getYear(new Date())}</Copy>
|
||||||
<StyledLink href="http://satoshilabs.com" target="_blank" rel="noreferrer noopener" isGreen>SatoshiLabs</StyledLink>
|
<StyledLink href="http://satoshilabs.com" target="_blank" rel="noreferrer noopener" isGreen>SatoshiLabs</StyledLink>
|
||||||
|
@ -1,8 +1,24 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import styled, { keyframes } from 'styled-components';
|
import styled, { keyframes } from 'styled-components';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
icon: Array<string>,
|
||||||
|
className?: string,
|
||||||
|
hoverColor?: string,
|
||||||
|
canAnimate?: boolean,
|
||||||
|
size?: number,
|
||||||
|
isActive?: boolean,
|
||||||
|
color?: string,
|
||||||
|
onMouseEnter?: () => void,
|
||||||
|
onMouseLeave?: () => void,
|
||||||
|
onFocus?: () => void,
|
||||||
|
onClick?: () => void,
|
||||||
|
}
|
||||||
|
|
||||||
const chooseIconAnimationType = (canAnimate, isActive) => {
|
const chooseIconAnimationType = (canAnimate, isActive) => {
|
||||||
if (canAnimate) {
|
if (canAnimate) {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
@ -58,7 +74,7 @@ const Icon = ({
|
|||||||
onMouseLeave,
|
onMouseLeave,
|
||||||
onFocus,
|
onFocus,
|
||||||
onClick,
|
onClick,
|
||||||
}) => (
|
}: Props) => (
|
||||||
<SvgWrapper
|
<SvgWrapper
|
||||||
className={className}
|
className={className}
|
||||||
canAnimate={canAnimate}
|
canAnimate={canAnimate}
|
||||||
@ -101,5 +117,4 @@ Icon.propTypes = {
|
|||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default Icon;
|
export default Icon;
|
@ -1,10 +1,23 @@
|
|||||||
import React from 'react';
|
/* @flow */
|
||||||
|
|
||||||
|
import * as 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 Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import { TRANSITION } from 'config/variables';
|
import { TRANSITION } from 'config/variables';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
type: string;
|
||||||
|
icon?: {
|
||||||
|
type: Array<string>;
|
||||||
|
color: string;
|
||||||
|
size: number;
|
||||||
|
};
|
||||||
|
onClick: () => void;
|
||||||
|
children: React.Node;
|
||||||
|
};
|
||||||
|
|
||||||
const Wrapper = styled.button`
|
const Wrapper = styled.button`
|
||||||
padding: 12px 58px;
|
padding: 12px 58px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
@ -62,10 +75,9 @@ const IconWrapper = styled.span`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const NotificationButton = ({
|
const NotificationButton = ({
|
||||||
children, className, icon, onClick = () => { }, type = null,
|
type, icon, onClick, children,
|
||||||
}) => (
|
}: Props) => (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
className={className}
|
|
||||||
icon={icon}
|
icon={icon}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
type={type}
|
type={type}
|
||||||
@ -84,15 +96,14 @@ const NotificationButton = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
NotificationButton.propTypes = {
|
NotificationButton.propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
|
||||||
type: PropTypes.string.isRequired,
|
type: PropTypes.string.isRequired,
|
||||||
className: PropTypes.string,
|
|
||||||
onClick: PropTypes.func,
|
|
||||||
icon: PropTypes.shape({
|
icon: PropTypes.shape({
|
||||||
type: PropTypes.arrayOf(PropTypes.string).isRequired,
|
type: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||||
color: PropTypes.string,
|
color: PropTypes.string,
|
||||||
size: PropTypes.number,
|
size: PropTypes.number,
|
||||||
}),
|
}),
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NotificationButton;
|
export default NotificationButton;
|
@ -1,9 +1,8 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
import React from 'react';
|
import * as React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import media from 'styled-media-query';
|
import media from 'styled-media-query';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import styled, { css } from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import { getColor, getIcon } from 'utils/notification';
|
import { getColor, getIcon } from 'utils/notification';
|
||||||
@ -13,21 +12,17 @@ import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
|
|||||||
|
|
||||||
import * as NotificationActions from 'actions/NotificationActions';
|
import * as NotificationActions from 'actions/NotificationActions';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import type { Action, State } from 'flowtype';
|
import type { CallbackAction } from 'reducers/NotificationReducer';
|
||||||
|
|
||||||
import NotificationButton from './components/NotificationButton';
|
import NotificationButton from './components/NotificationButton';
|
||||||
|
|
||||||
type Props = {
|
|
||||||
key?: number,
|
|
||||||
notifications: $ElementType<State, 'notifications'>,
|
|
||||||
close: (notif?: any) => Action,
|
|
||||||
};
|
|
||||||
|
|
||||||
type NProps = {
|
type Props = {
|
||||||
type: string,
|
type: string,
|
||||||
cancelable?: boolean;
|
cancelable?: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
message?: string;
|
message?: string;
|
||||||
actions?: Array<any>;
|
actions?: Array<CallbackAction>;
|
||||||
close?: typeof NotificationActions.close,
|
close?: typeof NotificationActions.close,
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
};
|
};
|
||||||
@ -128,10 +123,9 @@ const ActionContent = styled.div`
|
|||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Notification = (props: NProps): React$Element<string> => {
|
const Notification = (props: Props): React$Element<string> => {
|
||||||
const close: Function = typeof props.close === 'function' ? props.close : () => {}; // TODO: add default close action
|
const close: Function = typeof props.close === 'function' ? props.close : () => {}; // TODO: add default close action
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper type={props.type}>
|
<Wrapper type={props.type}>
|
||||||
{props.loading && <Loader size={50} /> }
|
{props.loading && <Loader size={50} /> }
|
||||||
@ -167,7 +161,6 @@ export const Notification = (props: NProps): React$Element<string> => {
|
|||||||
<NotificationButton
|
<NotificationButton
|
||||||
key={action.label}
|
key={action.label}
|
||||||
type={props.type}
|
type={props.type}
|
||||||
text={action.label}
|
|
||||||
onClick={() => { close(); action.callback(); }}
|
onClick={() => { close(); action.callback(); }}
|
||||||
>{action.label}
|
>{action.label}
|
||||||
</NotificationButton>
|
</NotificationButton>
|
||||||
@ -179,26 +172,14 @@ export const Notification = (props: NProps): React$Element<string> => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NotificationGroup = (props: Props) => {
|
Notification.propTypes = {
|
||||||
const { notifications, close } = props;
|
type: PropTypes.string.isRequired,
|
||||||
return notifications.map(n => (
|
cancelable: PropTypes.bool,
|
||||||
<Notification
|
title: PropTypes.string.isRequired,
|
||||||
key={n.title}
|
message: PropTypes.string,
|
||||||
type={n.type}
|
actions: PropTypes.arrayOf(PropTypes.object),
|
||||||
title={n.title}
|
close: PropTypes.func,
|
||||||
message={n.message}
|
loading: PropTypes.bool,
|
||||||
cancelable={n.cancelable}
|
|
||||||
actions={n.actions}
|
|
||||||
close={close}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default Notification;
|
||||||
state => ({
|
|
||||||
notifications: state.notifications,
|
|
||||||
}),
|
|
||||||
dispatch => ({
|
|
||||||
close: bindActionCreators(NotificationActions.close, dispatch),
|
|
||||||
}),
|
|
||||||
)(NotificationGroup);
|
|
@ -1,11 +1,11 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
|
|
||||||
import type { Props } from '../../index';
|
import type { Props } from '../../index';
|
||||||
|
|
||||||
export default (props: Props) => {
|
export default (props: Props) => {
|
||||||
const { online } = props.wallet;
|
const { online } = props.wallet;
|
||||||
if (online) return null;
|
if (online) return null;
|
||||||
return (<Notification type="error" title="Wallet is offline" />);
|
return (<Notification key="wallet-offline" type="error" title="Wallet is offline" />);
|
||||||
};
|
};
|
@ -1,6 +1,6 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
|
|
||||||
import type { Props } from '../../index';
|
import type { Props } from '../../index';
|
||||||
|
|
||||||
@ -8,6 +8,7 @@ export default (props: Props) => {
|
|||||||
if (props.connect.transport && props.connect.transport.outdated) {
|
if (props.connect.transport && props.connect.transport.outdated) {
|
||||||
return (
|
return (
|
||||||
<Notification
|
<Notification
|
||||||
|
key="update-bridge"
|
||||||
type="warning"
|
type="warning"
|
||||||
title="New Trezor Bridge is available"
|
title="New Trezor Bridge is available"
|
||||||
actions={
|
actions={
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
|
|
||||||
import type { Props } from '../../index';
|
import type { Props } from '../../index';
|
||||||
|
|
||||||
@ -10,6 +10,7 @@ export default (props: Props) => {
|
|||||||
if (!outdated) return null;
|
if (!outdated) return null;
|
||||||
return (
|
return (
|
||||||
<Notification
|
<Notification
|
||||||
|
key="update-firmware"
|
||||||
type="warning"
|
type="warning"
|
||||||
title="Firmware update"
|
title="Firmware update"
|
||||||
actions={
|
actions={
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
|
|
||||||
import type { Props } from '../../index';
|
import type { Props } from '../../index';
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import styled from 'styled-components';
|
|||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import ICONS from 'config/icons';
|
import ICONS from 'config/icons';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
import { getIcon, getColor } from 'utils/notification';
|
import { getIcon, getColor } from 'utils/notification';
|
||||||
|
|
||||||
const Wrapper = styled.div``;
|
const Wrapper = styled.div``;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
import { Notification } from 'components/Notification';
|
|
||||||
|
import * as React from 'react';
|
||||||
|
import Notification from 'components/Notification';
|
||||||
|
|
||||||
import type { Props } from '../../index';
|
import type { Props } from '../../index';
|
||||||
|
|
||||||
@ -8,9 +10,14 @@ export default (props: Props) => {
|
|||||||
if (!location) return null;
|
if (!location) return null;
|
||||||
|
|
||||||
const notifications: Array<Notification> = [];
|
const notifications: Array<Notification> = [];
|
||||||
|
// Example:
|
||||||
// if (location.state.device) {
|
// if (location.state.device) {
|
||||||
// notifications.push(<Notification key="example" type="info" title="Static example" />);
|
// notifications.push(<Notification key="example" type="info" title="Static example" />);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return notifications;
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{notifications}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
};
|
};
|
@ -1,6 +1,5 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
|
|
||||||
import { DEVICE } from 'trezor-connect';
|
import { DEVICE } from 'trezor-connect';
|
||||||
import type { Device } from 'trezor-connect';
|
import type { Device } from 'trezor-connect';
|
||||||
import * as CONNECT from 'actions/constants/TrezorConnect';
|
import * as CONNECT from 'actions/constants/TrezorConnect';
|
||||||
|
@ -13,6 +13,7 @@ export type CallbackAction = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type NotificationEntry = {
|
export type NotificationEntry = {
|
||||||
|
+key: string; // React.Key
|
||||||
+id: ?string;
|
+id: ?string;
|
||||||
+devicePath: ?string;
|
+devicePath: ?string;
|
||||||
+type: string;
|
+type: string;
|
||||||
@ -38,6 +39,7 @@ const initialState: State = [
|
|||||||
const addNotification = (state: State, payload: any): State => {
|
const addNotification = (state: State, payload: any): State => {
|
||||||
const newState: State = state.filter(e => !e.cancelable);
|
const newState: State = state.filter(e => !e.cancelable);
|
||||||
newState.push({
|
newState.push({
|
||||||
|
key: new Date().getTime().toString(),
|
||||||
id: payload.id,
|
id: payload.id,
|
||||||
devicePath: payload.devicePath,
|
devicePath: payload.devicePath,
|
||||||
type: payload.type,
|
type: payload.type,
|
||||||
|
11
src/store.js
11
src/store.js
@ -46,9 +46,8 @@ if (process.env.NODE_ENV === 'development') {
|
|||||||
collapsed: true,
|
collapsed: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { devToolsExtension }: ?Function = window;
|
if (window && typeof window.devToolsExtension === 'function') {
|
||||||
if (typeof devToolsExtension === 'function') {
|
enhancers.push(window.devToolsExtension());
|
||||||
enhancers.push(devToolsExtension());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
composedEnhancers = compose(
|
composedEnhancers = compose(
|
||||||
@ -67,9 +66,3 @@ export default createStore(
|
|||||||
initialState,
|
initialState,
|
||||||
composedEnhancers,
|
composedEnhancers,
|
||||||
);
|
);
|
||||||
|
|
||||||
// if (process.env.NODE_ENV === 'production') {
|
|
||||||
// module.exports = require('./store.dev'); // eslint-disable-line global-require
|
|
||||||
// } else {
|
|
||||||
// module.exports = require('./store.dev'); // eslint-disable-line global-require
|
|
||||||
// }
|
|
@ -19,7 +19,7 @@ export type StateProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DispatchProps = {
|
type DispatchProps = {
|
||||||
|
selectFirstAvailableDevice: typeof RouterActions.selectFirstAvailableDevice,
|
||||||
}
|
}
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
min-width: 720px;
|
min-width: 720px;
|
||||||
|
@ -12,6 +12,7 @@ import Loader from 'components/Loader';
|
|||||||
import P from 'components/Paragraph';
|
import P from 'components/Paragraph';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import ICONS from 'config/icons';
|
import ICONS from 'config/icons';
|
||||||
|
import * as RouterActions from 'actions/RouterActions';
|
||||||
|
|
||||||
import type { State as TrezorConnectState } from 'reducers/TrezorConnectReducer';
|
import type { State as TrezorConnectState } from 'reducers/TrezorConnectReducer';
|
||||||
|
|
||||||
|
@ -7,7 +7,8 @@ import Footer from 'components/Footer';
|
|||||||
import Log from 'components/Log';
|
import Log from 'components/Log';
|
||||||
import Link from 'components/Link';
|
import Link from 'components/Link';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import Notifications, { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
|
import ContextNotifications from 'components/notifications/Context';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import P from 'components/Paragraph';
|
import P from 'components/Paragraph';
|
||||||
import { H2 } from 'components/Heading';
|
import { H2 } from 'components/Heading';
|
||||||
@ -98,7 +99,7 @@ export default (props: Props) => {
|
|||||||
type="error"
|
type="error"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Notifications />
|
<ContextNotifications />
|
||||||
{shouldShowInitializationError && <InitializationError error={connectError} />}
|
{shouldShowInitializationError && <InitializationError error={connectError} />}
|
||||||
<Log />
|
<Log />
|
||||||
<LandingContent>
|
<LandingContent>
|
||||||
|
@ -107,7 +107,7 @@ const DiscoveryLoadingText = styled.span`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
// TODO: Refactorize deviceStatus & selectedAccounts
|
// TODO: Refactorize deviceStatus & selectedAccounts
|
||||||
const AccountMenu = (props: Props): ?React$Element<string> => {
|
const AccountMenu = (props: Props) => {
|
||||||
const selected = props.wallet.selectedDevice;
|
const selected = props.wallet.selectedDevice;
|
||||||
const { location } = props.router;
|
const { location } = props.router;
|
||||||
const urlParams = location.state;
|
const urlParams = location.state;
|
||||||
@ -117,7 +117,7 @@ const AccountMenu = (props: Props): ?React$Element<string> => {
|
|||||||
const { config } = props.localStorage;
|
const { config } = props.localStorage;
|
||||||
const selectedCoin = config.coins.find(c => c.network === location.state.network);
|
const selectedCoin = config.coins.find(c => c.network === location.state.network);
|
||||||
|
|
||||||
if (!selected || !selectedCoin) return;
|
if (!selected || !selectedCoin) return null;
|
||||||
|
|
||||||
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
|
const fiatRate = props.fiat.find(f => f.network === selectedCoin.network);
|
||||||
|
|
||||||
|
@ -1,7 +1,20 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
pathname: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
style: {
|
||||||
|
width: number;
|
||||||
|
left: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
@ -13,8 +26,6 @@ const Wrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
class Indicator extends Component<Props, State> {
|
class Indicator extends Component<Props, State> {
|
||||||
reposition: () => void;
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -28,25 +39,19 @@ class Indicator extends Component<Props, State> {
|
|||||||
this.reposition = this.reposition.bind(this);
|
this.reposition = this.reposition.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
state: State;
|
|
||||||
|
|
||||||
handleResize() {
|
|
||||||
this.reposition();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.reposition();
|
this.reposition();
|
||||||
window.addEventListener('resize', this.reposition, false);
|
window.addEventListener('resize', this.reposition, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
window.removeEventListener('resize', this.reposition, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
this.reposition();
|
this.reposition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener('resize', this.reposition, false);
|
||||||
|
}
|
||||||
|
|
||||||
reposition() {
|
reposition() {
|
||||||
const tabs = document.querySelector('.account-tabs');
|
const tabs = document.querySelector('.account-tabs');
|
||||||
if (!tabs) return;
|
if (!tabs) return;
|
||||||
@ -66,6 +71,12 @@ class Indicator extends Component<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reposition: () => void;
|
||||||
|
|
||||||
|
handleResize() {
|
||||||
|
this.reposition();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Wrapper style={this.state.style}>{ this.props.pathname }</Wrapper>
|
<Wrapper style={this.state.style}>{ this.props.pathname }</Wrapper>
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FONT_SIZE } from 'config/variables';
|
import { FONT_SIZE } from 'config/variables';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
|
|
||||||
|
import type { Location } from 'react-router';
|
||||||
|
|
||||||
import Indicator from './components/Indicator';
|
import Indicator from './components/Indicator';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
location: Location;
|
||||||
|
};
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -39,9 +48,11 @@ const StyledNavLink = styled(NavLink)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
||||||
const TopNavigationAccount = (props) => {
|
const TopNavigationAccount = (props: Props) => {
|
||||||
const urlParams = props.match.params;
|
const { state, pathname } = props.location;
|
||||||
const basePath = `/device/${urlParams.device}/network/${urlParams.network}/account/${urlParams.account}`;
|
if (!state) return null;
|
||||||
|
|
||||||
|
const basePath = `/device/${state.device}/network/${state.network}/account/${state.account}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper className="account-tabs">
|
<Wrapper className="account-tabs">
|
||||||
@ -49,7 +60,7 @@ const TopNavigationAccount = (props) => {
|
|||||||
<StyledNavLink to={`${basePath}/receive`}>Receive</StyledNavLink>
|
<StyledNavLink to={`${basePath}/receive`}>Receive</StyledNavLink>
|
||||||
<StyledNavLink to={`${basePath}/send`}>Send</StyledNavLink>
|
<StyledNavLink to={`${basePath}/send`}>Send</StyledNavLink>
|
||||||
{/* <StyledNavLink to={`${basePath}/signverify`}>Sign & Verify</StyledNavLink> */}
|
{/* <StyledNavLink to={`${basePath}/signverify`}>Sign & Verify</StyledNavLink> */}
|
||||||
<Indicator pathname={props.match.pathname} />
|
<Indicator pathname={pathname} />
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ import styled from 'styled-components';
|
|||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
import * as TrezorConnectActions from 'actions/TrezorConnectActions';
|
import * as TrezorConnectActions from 'actions/TrezorConnectActions';
|
||||||
|
|
||||||
import type { State, Dispatch } from 'flowtype';
|
import type { State, Dispatch } from 'flowtype';
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Notification } from 'components/Notification';
|
import Notification from 'components/Notification';
|
||||||
|
|
||||||
const Wrapper = styled.div``;
|
const Wrapper = styled.div``;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user