diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index 9ecc92c8..d3813a22 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -71,9 +71,7 @@ export type TrezorConnectAction = { type: typeof CONNECT.DEVICE_FROM_STORAGE, payload: Array<TrezorDevice> } | { - type: typeof CONNECT.START_ACQUIRING, -} | { - type: typeof CONNECT.STOP_ACQUIRING, + type: typeof CONNECT.START_ACQUIRING | typeof CONNECT.STOP_ACQUIRING, }; export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => { @@ -128,10 +126,10 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS pendingTransportEvent: (getState().devices.length < 1), }); } catch (error) { - // dispatch({ - // type: CONNECT.INITIALIZATION_ERROR, - // error - // }) + dispatch({ + type: CONNECT.INITIALIZATION_ERROR, + error, + }); } }; diff --git a/src/reducers/DevicesReducer.js b/src/reducers/DevicesReducer.js index f75d991d..538c096a 100644 --- a/src/reducers/DevicesReducer.js +++ b/src/reducers/DevicesReducer.js @@ -94,7 +94,6 @@ const addDevice = (state: State, device: Device): State => { const newDevice: TrezorDevice = device.type === 'acquired' ? { ...device, - // acquiring: false, ...extended, } : { ...device, @@ -132,8 +131,8 @@ const addDevice = (state: State, device: Device): State => { const changedDevices: Array<TrezorDevice> = affectedDevices.filter(d => d.features && device.features && d.features.passphrase_protection === device.features.passphrase_protection).map((d) => { - const extended: Object = { connected: true, available: true }; - return mergeDevices(d, { ...device, ...extended }); + const extended2: Object = { connected: true, available: true }; + return mergeDevices(d, { ...device, ...extended2 }); }); if (changedDevices.length !== affectedDevices.length) { changedDevices.push(newDevice); @@ -154,7 +153,6 @@ const duplicate = (state: State, device: TrezorDevice): State => { const newDevice: TrezorDevice = { ...device, - // acquiring: false, remember: false, state: null, // instance, (instance is already part of device - added in modal) @@ -199,7 +197,7 @@ const authDevice = (state: State, device: TrezorDevice, deviceState: string): St // Transform JSON form local storage into State -const devicesFromStorage = (devices: Array<TrezorDevice>): State => devices.map((device: TrezorDevice) => { +const devicesFromStorage = ($devices: Array<TrezorDevice>): State => $devices.map((device: TrezorDevice) => { const extended = { connected: false, available: false, @@ -233,14 +231,14 @@ const disconnectDevice = (state: State, device: Device): State => { const otherDevices: State = state.filter(d => affectedDevices.indexOf(d) === -1); if (affectedDevices.length > 0) { - const acquiredDevices = affectedDevices.filter(d => d.features && d.state).map((d) => { - if (d.type === 'acquired') { - d.connected = false; - d.available = false; - d.status = 'available'; - d.path = ''; - } - return d; + const acquiredDevices = affectedDevices.filter(d => d.features && d.state).map((d) => { // eslint-disable-line arrow-body-style + return d.type === 'acquired' ? { + ...d, + connected: false, + available: false, + status: 'available', + path: '', + } : d; }); return otherDevices.concat(acquiredDevices); } @@ -249,12 +247,18 @@ const disconnectDevice = (state: State, device: Device): State => { }; const onSelectedDevice = (state: State, device: ?TrezorDevice): State => { - if (device) { - const otherDevices: Array<TrezorDevice> = state.filter(d => d !== device); - device.ts = new Date().getTime(); - return otherDevices.concat([device]); - } - return state; + if (!device) return state; + + const otherDevices: Array<TrezorDevice> = state.filter(d => d !== device); + const extended = device.type === 'acquired' ? { + ...device, + ts: new Date().getTime(), + } : { + ...device, + features: null, + ts: new Date().getTime(), + }; + return otherDevices.concat([extended]); }; export default function devices(state: State = initialState, action: Action): State { diff --git a/src/reducers/TrezorConnectReducer.js b/src/reducers/TrezorConnectReducer.js index f6e48630..f8adf4dd 100644 --- a/src/reducers/TrezorConnectReducer.js +++ b/src/reducers/TrezorConnectReducer.js @@ -10,9 +10,7 @@ export type SelectedDevice = { } export type State = { - // devices: Array<TrezorDevice>; - // selectedDevice: ?SelectedDevice; - discoveryComplete: boolean; + initialized: boolean; error: ?string; transport: ?{ type: string; @@ -26,54 +24,42 @@ export type State = { // mobile: boolean; // } | {}; browserState: any; - acquiring: boolean; + acquiringDevice: boolean; } - const initialState: State = { - // devices: [], - //selectedDevice: null, - discoveryComplete: false, + initialized: false, error: null, transport: null, browserState: {}, - acquiring: false, + acquiringDevice: false, }; export default function connect(state: State = initialState, action: Action): State { switch (action.type) { - case UI.IFRAME_HANDSHAKE: - return { - ...state, - browserState: action.payload.browser, - }; - - case CONNECT.START_ACQUIRING: - return { - ...state, - acquiring: true, - }; - - case CONNECT.STOP_ACQUIRING: - return { - ...state, - acquiring: false, - }; - + // trezor-connect iframe didn't loaded properly case CONNECT.INITIALIZATION_ERROR: return { ...state, error: action.error, }; - + // trezor-connect iframe loaded + case UI.IFRAME_HANDSHAKE: + return { + ...state, + initialized: true, + browserState: action.payload.browser, + }; + // trezor-connect (trezor-link) initialized case TRANSPORT.START: return { ...state, transport: action.payload, error: null, }; - + // trezor-connect (trezor-link) + // will be called continuously in interval until connection (bridge/webusb) will be established case TRANSPORT.ERROR: return { ...state, @@ -82,6 +68,17 @@ export default function connect(state: State = initialState, action: Action): St transport: null, }; + case CONNECT.START_ACQUIRING: + return { + ...state, + acquiringDevice: true, + }; + + case CONNECT.STOP_ACQUIRING: + return { + ...state, + acquiringDevice: false, + }; default: return state; diff --git a/src/views/Landing/components/InitializationError/index.js b/src/views/Landing/components/InitializationError/index.js new file mode 100644 index 00000000..2db65aee --- /dev/null +++ b/src/views/Landing/components/InitializationError/index.js @@ -0,0 +1,23 @@ +/* @flow */ + +import React from 'react'; +import styled from 'styled-components'; +import { Notification } from 'components/Notification'; + +const Wrapper = styled.div` + min-width: 720px; + width: 100%; +`; + +const InitializationError = (props: { error: ?string }) => ( + <Wrapper> + <Notification + title="Initialization error" + message={props.error || ''} + type="error" + cancelable={false} + /> + </Wrapper> +); + +export default InitializationError; \ No newline at end of file diff --git a/src/views/Landing/index.js b/src/views/Landing/index.js index 398b9ef4..13ec9331 100644 --- a/src/views/Landing/index.js +++ b/src/views/Landing/index.js @@ -14,6 +14,7 @@ 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'; @@ -77,13 +78,13 @@ export default (props: Props) => { const bridgeRoute: boolean = props.router.location.state.hasOwnProperty('bridge'); const deviceLabel = props.wallet.disconnectRequest ? props.wallet.disconnectRequest.label : ''; - const shouldShowInstallBridge = connectError || bridgeRoute; + 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 = !shouldShowInstallBridge && !shouldShowConnectDevice && !shouldShowUnsupportedBrowser && !localStorageError; - + const isLoading = !shouldShowInitializationError && !shouldShowInstallBridge && !shouldShowConnectDevice && !shouldShowUnsupportedBrowser && !localStorageError; return ( <LandingWrapper> {isLoading && <LandingLoader text="Loading" size={100} />} @@ -98,10 +99,9 @@ export default (props: Props) => { /> )} <Notifications /> + {shouldShowInitializationError && <InitializationError error={connectError} />} <Log /> - <LandingContent> - {shouldShowUnsupportedBrowser && <BrowserNotSupported />} {shouldShowInstallBridge && <InstallBridge browserState={browserState} />} diff --git a/src/views/Wallet/views/Acquire/index.js b/src/views/Wallet/views/Acquire/index.js index 618a7a1f..b514b9c7 100644 --- a/src/views/Wallet/views/Acquire/index.js +++ b/src/views/Wallet/views/Acquire/index.js @@ -46,7 +46,7 @@ const Acquire = (props: Props) => { export default connect( (state: State) => ({ - acquiring: state.connect.acquiring, + acquiring: state.connect.acquiringDevice, }), (dispatch: Dispatch) => ({ acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch), diff --git a/src/views/Wallet/views/UnreadableDevice/index.js b/src/views/Wallet/views/UnreadableDevice/index.js index a9f0273b..15e99283 100644 --- a/src/views/Wallet/views/UnreadableDevice/index.js +++ b/src/views/Wallet/views/UnreadableDevice/index.js @@ -1,14 +1,8 @@ /* @flow */ - import React from 'react'; -import { bindActionCreators } from 'redux'; -import { connect } from 'react-redux'; import styled from 'styled-components'; import { Notification } from 'components/Notification'; -import * as TrezorConnectActions from 'actions/TrezorConnectActions'; - -import type { State, Dispatch } from 'flowtype'; const Wrapper = styled.div``; @@ -23,11 +17,4 @@ const UnreadableDevice = () => ( </Wrapper> ); -export default connect( - (state: State) => ({ - acquiring: state.connect.acquiring, - }), - (dispatch: Dispatch) => ({ - acquireDevice: bindActionCreators(TrezorConnectActions.acquire, dispatch), - }), -)(UnreadableDevice); +export default UnreadableDevice;