diff --git a/.eslintignore b/.eslintignore index ec297d25..be07de15 100644 --- a/.eslintignore +++ b/.eslintignore @@ -3,4 +3,5 @@ build build-devel coverage node_modules -src/flowtype/npm \ No newline at end of file +src/flowtype/npm +**/_old/* \ No newline at end of file diff --git a/src/components/Button/index.js b/src/components/Button/index.js index 62d1661b..cae9bcab 100644 --- a/src/components/Button/index.js +++ b/src/components/Button/index.js @@ -1,9 +1,24 @@ -import React from 'react'; +/* @flow */ + +import * as React from 'react'; import styled, { css } from 'styled-components'; import PropTypes from 'prop-types'; import colors from 'config/colors'; 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` padding: ${props => (props.icon ? '4px 24px 4px 15px' : '11px 24px')}; border-radius: 3px; @@ -108,8 +123,8 @@ const Wrapper = styled.button` const Button = ({ children, - className, - onClick = () => { }, + className = '', + onClick, onMouseEnter, onMouseLeave, onFocus, @@ -117,7 +132,7 @@ const Button = ({ isWhite = false, isWebUsb = false, isTransparent = false, -}) => { +}: Props) => { const newClassName = isWebUsb ? `${className} trezor-webusb-button` : className; return ( void, + isChecked: boolean, + children: string, +} + const Wrapper = styled.div` display: flex; flex-direction: row; @@ -54,10 +62,10 @@ const Label = styled.div` } `; -class Checkbox extends PureComponent { - handleKeyboard(e) { - if (e.keyCode === 32) { - this.props.onClick(e); +class Checkbox extends PureComponent { + handleKeyboard(event: KeyboardEvent) { + if (event.keyCode === 32) { + this.props.onClick(event); } } @@ -70,7 +78,7 @@ class Checkbox extends PureComponent { return ( this.handleKeyboard(e)} + onKeyUp={event => this.handleKeyboard(event)} tabIndex={0} > diff --git a/src/components/Footer/index.js b/src/components/Footer/index.js index 0c443223..dea133db 100644 --- a/src/components/Footer/index.js +++ b/src/components/Footer/index.js @@ -11,6 +11,11 @@ import { connect } from 'react-redux'; import colors from 'config/colors'; import * as LogActions from 'actions/LogActions'; +type Props = { + opened: boolean, + toggle: () => any, +} + const Wrapper = styled.div` width: 100%; font-size: 12px; @@ -30,7 +35,7 @@ const Copy = styled.div` margin-right: 20px; `; -const Footer = ({ opened, toggle }) => ( +const Footer = ({ opened, toggle }: Props) => ( © {getYear(new Date())} SatoshiLabs diff --git a/src/components/Icon/index.js b/src/components/Icon/index.js index 05d5f749..7773a6d3 100644 --- a/src/components/Icon/index.js +++ b/src/components/Icon/index.js @@ -1,8 +1,24 @@ +/* @flow */ + import React from 'react'; import PropTypes from 'prop-types'; import colors from 'config/colors'; import styled, { keyframes } from 'styled-components'; +type Props = { + icon: Array, + className?: string, + hoverColor?: string, + canAnimate?: boolean, + size?: number, + isActive?: boolean, + color?: string, + onMouseEnter?: () => void, + onMouseLeave?: () => void, + onFocus?: () => void, + onClick?: () => void, +} + const chooseIconAnimationType = (canAnimate, isActive) => { if (canAnimate) { if (isActive) { @@ -58,7 +74,7 @@ const Icon = ({ onMouseLeave, onFocus, onClick, -}) => ( +}: Props) => ( ; + color: string; + size: number; + }; + onClick: () => void; + children: React.Node; +}; + const Wrapper = styled.button` padding: 12px 58px; border-radius: 3px; @@ -62,10 +75,9 @@ const IconWrapper = styled.span` `; const NotificationButton = ({ - children, className, icon, onClick = () => { }, type = null, -}) => ( + type, icon, onClick, children, +}: Props) => ( , - close: (notif?: any) => Action, -}; -type NProps = { +type Props = { type: string, cancelable?: boolean; title: string; message?: string; - actions?: Array; + actions?: Array; close?: typeof NotificationActions.close, loading?: boolean }; @@ -128,10 +123,9 @@ const ActionContent = styled.div` `} `; -export const Notification = (props: NProps): React$Element => { +const Notification = (props: Props): React$Element => { const close: Function = typeof props.close === 'function' ? props.close : () => {}; // TODO: add default close action - return ( {props.loading && } @@ -167,7 +161,6 @@ export const Notification = (props: NProps): React$Element => { { close(); action.callback(); }} >{action.label} @@ -179,26 +172,14 @@ export const Notification = (props: NProps): React$Element => { ); }; -export const NotificationGroup = (props: Props) => { - const { notifications, close } = props; - return notifications.map(n => ( - - )); +Notification.propTypes = { + type: PropTypes.string.isRequired, + cancelable: PropTypes.bool, + title: PropTypes.string.isRequired, + message: PropTypes.string, + actions: PropTypes.arrayOf(PropTypes.object), + close: PropTypes.func, + loading: PropTypes.bool, }; -export default connect( - state => ({ - notifications: state.notifications, - }), - dispatch => ({ - close: bindActionCreators(NotificationActions.close, dispatch), - }), -)(NotificationGroup); +export default Notification; \ No newline at end of file diff --git a/src/components/notifications/App/components/OnlineStatus/index.js b/src/components/notifications/App/components/OnlineStatus/index.js index b7712253..d5acc265 100644 --- a/src/components/notifications/App/components/OnlineStatus/index.js +++ b/src/components/notifications/App/components/OnlineStatus/index.js @@ -1,11 +1,11 @@ /* @flow */ import * as React from 'react'; -import { Notification } from 'components/Notification'; +import Notification from 'components/Notification'; import type { Props } from '../../index'; export default (props: Props) => { const { online } = props.wallet; if (online) return null; - return (); + return (); }; \ No newline at end of file diff --git a/src/components/notifications/App/components/UpdateBridge/index.js b/src/components/notifications/App/components/UpdateBridge/index.js index e418bb37..071dddde 100644 --- a/src/components/notifications/App/components/UpdateBridge/index.js +++ b/src/components/notifications/App/components/UpdateBridge/index.js @@ -1,6 +1,6 @@ /* @flow */ import * as React from 'react'; -import { Notification } from 'components/Notification'; +import Notification from 'components/Notification'; import type { Props } from '../../index'; @@ -8,6 +8,7 @@ export default (props: Props) => { if (props.connect.transport && props.connect.transport.outdated) { return ( { if (!outdated) return null; return ( { if (!location) return null; const notifications: Array = []; + // Example: // if (location.state.device) { // notifications.push(); // } - return notifications; + return ( + + {notifications} + + ); }; \ No newline at end of file diff --git a/src/reducers/DevicesReducer.js b/src/reducers/DevicesReducer.js index 0ed79b82..d7ca930a 100644 --- a/src/reducers/DevicesReducer.js +++ b/src/reducers/DevicesReducer.js @@ -1,6 +1,5 @@ /* @flow */ - import { DEVICE } from 'trezor-connect'; import type { Device } from 'trezor-connect'; import * as CONNECT from 'actions/constants/TrezorConnect'; diff --git a/src/reducers/NotificationReducer.js b/src/reducers/NotificationReducer.js index 0ca86f47..720d6883 100644 --- a/src/reducers/NotificationReducer.js +++ b/src/reducers/NotificationReducer.js @@ -13,6 +13,7 @@ export type CallbackAction = { } export type NotificationEntry = { + +key: string; // React.Key +id: ?string; +devicePath: ?string; +type: string; @@ -38,6 +39,7 @@ const initialState: State = [ const addNotification = (state: State, payload: any): State => { const newState: State = state.filter(e => !e.cancelable); newState.push({ + key: new Date().getTime().toString(), id: payload.id, devicePath: payload.devicePath, type: payload.type, diff --git a/src/store.js b/src/store.js index f5e985d6..39600b1a 100644 --- a/src/store.js +++ b/src/store.js @@ -46,9 +46,8 @@ if (process.env.NODE_ENV === 'development') { collapsed: true, }); - const { devToolsExtension }: ?Function = window; - if (typeof devToolsExtension === 'function') { - enhancers.push(devToolsExtension()); + if (window && typeof window.devToolsExtension === 'function') { + enhancers.push(window.devToolsExtension()); } composedEnhancers = compose( @@ -67,9 +66,3 @@ export default createStore( initialState, 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 -// } \ No newline at end of file diff --git a/src/views/Landing/Container.js b/src/views/Landing/Container.js index 2a58e643..d10ed485 100644 --- a/src/views/Landing/Container.js +++ b/src/views/Landing/Container.js @@ -19,7 +19,7 @@ export type StateProps = { } type DispatchProps = { - + selectFirstAvailableDevice: typeof RouterActions.selectFirstAvailableDevice, } type OwnProps = { diff --git a/src/views/Landing/components/InitializationError/index.js b/src/views/Landing/components/InitializationError/index.js index 2db65aee..a3fc17cb 100644 --- a/src/views/Landing/components/InitializationError/index.js +++ b/src/views/Landing/components/InitializationError/index.js @@ -2,7 +2,7 @@ import React from 'react'; import styled from 'styled-components'; -import { Notification } from 'components/Notification'; +import Notification from 'components/Notification'; const Wrapper = styled.div` min-width: 720px; diff --git a/src/views/Landing/components/InstallBridge/index.js b/src/views/Landing/components/InstallBridge/index.js index f62645d3..a53704ff 100644 --- a/src/views/Landing/components/InstallBridge/index.js +++ b/src/views/Landing/components/InstallBridge/index.js @@ -12,6 +12,7 @@ import Loader from 'components/Loader'; import P from 'components/Paragraph'; import Icon from 'components/Icon'; import ICONS from 'config/icons'; +import * as RouterActions from 'actions/RouterActions'; import type { State as TrezorConnectState } from 'reducers/TrezorConnectReducer'; diff --git a/src/views/Landing/index.js b/src/views/Landing/index.js index a7702939..7c6ea3e9 100644 --- a/src/views/Landing/index.js +++ b/src/views/Landing/index.js @@ -7,7 +7,8 @@ import Footer from 'components/Footer'; import Log from 'components/Log'; import Link from 'components/Link'; 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 P from 'components/Paragraph'; import { H2 } from 'components/Heading'; @@ -98,7 +99,7 @@ export default (props: Props) => { type="error" /> )} - + {shouldShowInitializationError && } diff --git a/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js b/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js index 1c238302..ba6cf83a 100644 --- a/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js @@ -107,7 +107,7 @@ const DiscoveryLoadingText = styled.span` `; // TODO: Refactorize deviceStatus & selectedAccounts -const AccountMenu = (props: Props): ?React$Element => { +const AccountMenu = (props: Props) => { const selected = props.wallet.selectedDevice; const { location } = props.router; const urlParams = location.state; @@ -117,7 +117,7 @@ const AccountMenu = (props: Props): ?React$Element => { const { config } = props.localStorage; 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); diff --git a/src/views/Wallet/components/TopNavigationAccount/components/Indicator/index.js b/src/views/Wallet/components/TopNavigationAccount/components/Indicator/index.js index e3c40e90..95c93e28 100644 --- a/src/views/Wallet/components/TopNavigationAccount/components/Indicator/index.js +++ b/src/views/Wallet/components/TopNavigationAccount/components/Indicator/index.js @@ -1,7 +1,20 @@ +/* @flow */ + import styled from 'styled-components'; import colors from 'config/colors'; import React, { Component } from 'react'; +type Props = { + pathname: string; +} + +type State = { + style: { + width: number; + left: number; + } +} + const Wrapper = styled.div` position: absolute; bottom: 0px; @@ -13,8 +26,6 @@ const Wrapper = styled.div` `; class Indicator extends Component { - reposition: () => void; - constructor(props: Props) { super(props); @@ -28,25 +39,19 @@ class Indicator extends Component { this.reposition = this.reposition.bind(this); } - state: State; - - handleResize() { - this.reposition(); - } - componentDidMount() { this.reposition(); window.addEventListener('resize', this.reposition, false); } - componentWillUnmount() { - window.removeEventListener('resize', this.reposition, false); - } - componentDidUpdate() { this.reposition(); } + componentWillUnmount() { + window.removeEventListener('resize', this.reposition, false); + } + reposition() { const tabs = document.querySelector('.account-tabs'); if (!tabs) return; @@ -66,6 +71,12 @@ class Indicator extends Component { } } + reposition: () => void; + + handleResize() { + this.reposition(); + } + render() { return ( { this.props.pathname } diff --git a/src/views/Wallet/components/TopNavigationAccount/index.js b/src/views/Wallet/components/TopNavigationAccount/index.js index 17058116..aef26440 100644 --- a/src/views/Wallet/components/TopNavigationAccount/index.js +++ b/src/views/Wallet/components/TopNavigationAccount/index.js @@ -1,10 +1,19 @@ +/* @flow */ + import styled from 'styled-components'; import React from 'react'; import { FONT_SIZE } from 'config/variables'; import { NavLink } from 'react-router-dom'; import colors from 'config/colors'; + +import type { Location } from 'react-router'; + import Indicator from './components/Indicator'; +type Props = { + location: Location; +}; + const Wrapper = styled.div` position: relative; display: flex; @@ -39,9 +48,11 @@ const StyledNavLink = styled(NavLink)` `; -const TopNavigationAccount = (props) => { - const urlParams = props.match.params; - const basePath = `/device/${urlParams.device}/network/${urlParams.network}/account/${urlParams.account}`; +const TopNavigationAccount = (props: Props) => { + const { state, pathname } = props.location; + if (!state) return null; + + const basePath = `/device/${state.device}/network/${state.network}/account/${state.account}`; return ( @@ -49,7 +60,7 @@ const TopNavigationAccount = (props) => { Receive Send {/* Sign & Verify */} - + ); }; diff --git a/src/views/Wallet/views/Acquire/index.js b/src/views/Wallet/views/Acquire/index.js index b514b9c7..1df45e01 100644 --- a/src/views/Wallet/views/Acquire/index.js +++ b/src/views/Wallet/views/Acquire/index.js @@ -4,7 +4,7 @@ import styled from 'styled-components'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import colors from 'config/colors'; -import { Notification } from 'components/Notification'; +import Notification from 'components/Notification'; import * as TrezorConnectActions from 'actions/TrezorConnectActions'; import type { State, Dispatch } from 'flowtype'; diff --git a/src/views/Wallet/views/UnreadableDevice/index.js b/src/views/Wallet/views/UnreadableDevice/index.js index 15e99283..e00e8956 100644 --- a/src/views/Wallet/views/UnreadableDevice/index.js +++ b/src/views/Wallet/views/UnreadableDevice/index.js @@ -2,7 +2,7 @@ import React from 'react'; import styled from 'styled-components'; -import { Notification } from 'components/Notification'; +import Notification from 'components/Notification'; const Wrapper = styled.div``;