From cb7fbb2e6921982fc91aaa8a89ff45bf11d347c6 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 15:31:03 +0200 Subject: [PATCH 01/20] added new field "useEmptyPassphrase" to TrezorDevice object --- src/flowtype/index.js | 2 ++ src/reducers/DevicesReducer.js | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/flowtype/index.js b/src/flowtype/index.js index 203033d1..44bd5556 100644 --- a/src/flowtype/index.js +++ b/src/flowtype/index.js @@ -56,6 +56,7 @@ export type AcquiredDevice = $Exact<{ status: DeviceStatus, +mode: DeviceMode, state: ?string, + useEmptyPassphrase: boolean, remember: boolean; // device should be remembered connected: boolean; // device is connected @@ -73,6 +74,7 @@ export type UnknownDevice = $Exact<{ +label: string, +features: null, state: ?string, + useEmptyPassphrase: boolean, remember: boolean; // device should be remembered connected: boolean; // device is connected diff --git a/src/reducers/DevicesReducer.js b/src/reducers/DevicesReducer.js index 81f2b4b1..e55b951c 100644 --- a/src/reducers/DevicesReducer.js +++ b/src/reducers/DevicesReducer.js @@ -39,6 +39,7 @@ const mergeDevices = (current: TrezorDevice, upcoming: Device | TrezorDevice): T instanceName: typeof upcoming.instanceName === 'string' ? upcoming.instanceName : current.instanceName, state: current.state, ts: typeof upcoming.ts === 'number' ? upcoming.ts : current.ts, + useEmptyPassphrase: typeof upcoming.useEmptyPassphrase === 'boolean' ? upcoming.useEmptyPassphrase : current.useEmptyPassphrase, }; if (upcoming.type === 'acquired') { @@ -89,6 +90,7 @@ const addDevice = (state: State, device: Device): State => { instanceLabel: device.label, instanceName: null, ts: new Date().getTime(), + useEmptyPassphrase: true, }; @@ -260,6 +262,22 @@ const onSelectedDevice = (state: State, device: ?TrezorDevice): State => { return otherDevices.concat([extended]); }; +const onChangeWalletType = (state: State, device: TrezorDevice, hidden: boolean): State => { + const affectedDevices: State = state.filter(d => d.path === device.path || (d.features && device.features && d.features.device_id === device.features.device_id)); + const otherDevices: State = state.filter(d => affectedDevices.indexOf(d) === -1); + if (affectedDevices.length > 0) { + const changedDevices = affectedDevices.map((d) => { // eslint-disable-line arrow-body-style + return d.type === 'acquired' ? { + ...d, + state: null, + useEmptyPassphrase: !hidden, + } : d; + }); + return otherDevices.concat(changedDevices); + } + return state; +}; + export default function devices(state: State = initialState, action: Action): State { switch (action.type) { case CONNECT.DEVICE_FROM_STORAGE: @@ -296,6 +314,9 @@ export default function devices(state: State = initialState, action: Action): St case WALLET.SET_SELECTED_DEVICE: return onSelectedDevice(state, action.device); + case CONNECT.RECEIVE_WALLET_TYPE: + return onChangeWalletType(state, action.device, action.hidden); + default: return state; } From df191fa7262c0fe188317989bef337dde1bef932 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 15:46:47 +0200 Subject: [PATCH 02/20] TrezorConnect calls using new field "useEmptyPassphrase" --- src/actions/DiscoveryActions.js | 6 ++++-- src/actions/ReceiveActions.js | 3 ++- src/actions/SendFormActions.js | 3 ++- .../components/DeviceMenu/components/MenuItems/index.js | 6 +++--- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index e9c02369..596bc335 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -142,7 +142,8 @@ const begin = (device: TrezorDevice, network: string): AsyncAction => async (dis }, path: coinToDiscover.bip44, keepSession: true, // acquire and hold session - useEmptyPassphrase: !device.instance, + //useEmptyPassphrase: !device.instance, + useEmptyPassphrase: device.useEmptyPassphrase, }); // handle TREZOR response error @@ -264,7 +265,8 @@ const finish = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction state: device.state, }, keepSession: false, - useEmptyPassphrase: !device.instance, + // useEmptyPassphrase: !device.instance, + useEmptyPassphrase: device.useEmptyPassphrase, }); await dispatch(BlockchainActions.subscribe(discoveryProcess.network)); diff --git a/src/actions/ReceiveActions.js b/src/actions/ReceiveActions.js index 6f193e48..95d56119 100644 --- a/src/actions/ReceiveActions.js +++ b/src/actions/ReceiveActions.js @@ -67,7 +67,8 @@ export const showAddress = (path: Array): AsyncAction => async (dispatch state: selected.state, }, path, - useEmptyPassphrase: !selected.instance, + // useEmptyPassphrase: !selected.instance, + useEmptyPassphrase: selected.useEmptyPassphrase, }); if (response && response.success) { diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index f26664f3..90ddf02e 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -458,7 +458,8 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge instance: selected.instance, state: selected.state, }, - useEmptyPassphrase: !selected.instance, + // useEmptyPassphrase: !selected.instance, + useEmptyPassphrase: selected.useEmptyPassphrase, path: account.addressPath, transaction: txData, }); diff --git a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/components/MenuItems/index.js b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/components/MenuItems/index.js index a52bb769..969d3363 100644 --- a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/components/MenuItems/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/components/MenuItems/index.js @@ -58,14 +58,14 @@ class MenuItems extends Component { if (!this.showDeviceMenu()) return null; return ( - this.onDeviceMenuClick('settings', this.props.device)}> + {/* this.onDeviceMenuClick('settings', this.props.device)}> - + */} this.onDeviceMenuClick('forget', this.props.device)}> - + )} {this.showRenewSession() && ( From bd6bb5927da2f46cc139c883abfb6445ae1a79e8 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 15:47:37 +0200 Subject: [PATCH 03/20] new actions: request and receive wallet type --- src/actions/TrezorConnectActions.js | 45 ++++++++++++++++++++++---- src/actions/WalletActions.js | 1 + src/actions/constants/TrezorConnect.js | 5 ++- src/services/WalletService.js | 23 ++++++++----- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index b54a97a0..8f0bd2e8 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -71,6 +71,13 @@ export type TrezorConnectAction = { payload: Array } | { type: typeof CONNECT.START_ACQUIRING | typeof CONNECT.STOP_ACQUIRING, +} | { + type: typeof CONNECT.REQUEST_WALLET_TYPE, + device: TrezorDevice +} | { + type: typeof CONNECT.RECEIVE_WALLET_TYPE, + device: TrezorDevice, + hidden: boolean, }; export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { @@ -152,7 +159,19 @@ export const postInit = (): ThunkAction => (dispatch: Dispatch): void => { } }; -export const getSelectedDeviceState = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const requestWalletType = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const selected = getState().wallet.selectedDevice; + if (!selected) return; + const isDeviceReady = selected.connected && selected.features && !selected.state && selected.mode === 'normal' && selected.firmware !== 'required'; + if (!isDeviceReady) return; + + dispatch({ + type: CONNECT.REQUEST_WALLET_TYPE, + device: selected, + }); +}; + +export const authorizeDevice = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { const selected = getState().wallet.selectedDevice; if (!selected) return; const isDeviceReady = selected.connected && selected.features && !selected.state && selected.mode === 'normal' && selected.firmware !== 'required'; @@ -164,7 +183,7 @@ export const getSelectedDeviceState = (): AsyncAction => async (dispatch: Dispat instance: selected.instance, state: selected.state, }, - useEmptyPassphrase: !selected.instance, + useEmptyPassphrase: selected.useEmptyPassphrase, }); if (response && response.success) { @@ -190,14 +209,13 @@ export const getSelectedDeviceState = (): AsyncAction => async (dispatch: Dispat type: NOTIFICATION.CLOSE, payload: { devicePath: selected.path }, }); - dispatch(getSelectedDeviceState()); + dispatch(authorizeDevice()); }, }, ], }, }); } - }; export const deviceDisconnect = (device: Device): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { @@ -231,11 +249,14 @@ export function acquire(): AsyncAction { type: CONNECT.START_ACQUIRING, }); + // this is the only place where useEmptyPassphrase should be used every time + // the goal here is to acquire device and get his features + // authentication (passphrase) is not needed here yet const response = await TrezorConnect.getFeatures({ device: { path: selected.path, }, - useEmptyPassphrase: !selected.instance, + useEmptyPassphrase: true, }); if (!response.success) { @@ -270,7 +291,7 @@ export const forget = (device: TrezorDevice): Action => ({ device, }); -export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const duplicateDevice1 = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { // dispatch({ // type: CONNECT.TRY_TO_DUPLICATE, // device, @@ -283,3 +304,15 @@ export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dis device: { ...device, ...extended }, }); }; + +export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { + // dispatch({ + // type: CONNECT.TRY_TO_DUPLICATE, + // device, + // }); + + dispatch({ + type: CONNECT.REQUEST_WALLET_TYPE, + device, + }); +}; diff --git a/src/actions/WalletActions.js b/src/actions/WalletActions.js index a7325d25..b477ce14 100644 --- a/src/actions/WalletActions.js +++ b/src/actions/WalletActions.js @@ -87,6 +87,7 @@ export const clearUnavailableDevicesData = (prevState: State, device: Device): T const actions = [ LOCATION_CHANGE, CONNECT.AUTH_DEVICE, + CONNECT.RECEIVE_WALLET_TYPE, ...Object.values(DEVICE).filter(v => typeof v === 'string'), ]; diff --git a/src/actions/constants/TrezorConnect.js b/src/actions/constants/TrezorConnect.js index a49371c5..7a6a446d 100644 --- a/src/actions/constants/TrezorConnect.js +++ b/src/actions/constants/TrezorConnect.js @@ -25,4 +25,7 @@ export const DUPLICATE: 'connect__duplicate' = 'connect__duplicate'; export const DEVICE_STATE_EXCEPTION: 'connect__device_state_exception' = 'connect__device_state_exception'; export const START_ACQUIRING: 'connect__start_acquiring' = 'connect__start_acquiring'; -export const STOP_ACQUIRING: 'connect__stop_acquiring' = 'connect__stop_acquiring'; \ No newline at end of file +export const STOP_ACQUIRING: 'connect__stop_acquiring' = 'connect__stop_acquiring'; + +export const REQUEST_WALLET_TYPE: 'connect__request_wallet_type' = 'connect__request_wallet_type'; +export const RECEIVE_WALLET_TYPE: 'connect__receive_wallet_type' = 'connect__receive_wallet_type'; \ No newline at end of file diff --git a/src/services/WalletService.js b/src/services/WalletService.js index 3cfe4ddb..0e2b87d2 100644 --- a/src/services/WalletService.js +++ b/src/services/WalletService.js @@ -49,10 +49,9 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa api.dispatch(LocalStorageActions.loadData()); break; case WALLET.SET_SELECTED_DEVICE: - if (action.device) { - // try to authorize device - api.dispatch(TrezorConnectActions.getSelectedDeviceState()); - } + // try to authorize device + // api.dispatch(TrezorConnectActions.authorizeDevice()); + api.dispatch(TrezorConnectActions.requestWalletType()); break; case DEVICE.CONNECT: api.dispatch(WalletActions.clearUnavailableDevicesData(prevState, action.device)); @@ -102,10 +101,18 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa // if "selectedAccount" didn't change observe send form props changes api.dispatch(SendFormActionActions.observe(prevState, action)); } - } else if (action.type === CONNECT.AUTH_DEVICE) { - // selected device did changed - // try to restore discovery after device authentication - api.dispatch(DiscoveryActions.restore()); + } else { + switch (action.type) { + case CONNECT.AUTH_DEVICE: + // selected device did changed + // try to restore discovery after device authentication + api.dispatch(DiscoveryActions.restore()); + break; + case CONNECT.RECEIVE_WALLET_TYPE: + api.dispatch(TrezorConnectActions.authorizeDevice()); + break; + default: break; + } } // even if "selectedDevice" didn't change because it was updated on DEVICE.CHANGED before DEVICE.CONNECT action From c570970b423c398d0ee59ef52546efdff78f35a7 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 15:47:51 +0200 Subject: [PATCH 04/20] new modal "wallet type" --- src/actions/ModalActions.js | 12 ++++ src/components/modals/device/Type/index.js | 70 ++++++++++++++++++++++ src/components/modals/index.js | 5 ++ src/reducers/ModalReducer.js | 7 +++ 4 files changed, 94 insertions(+) create mode 100644 src/components/modals/device/Type/index.js diff --git a/src/actions/ModalActions.js b/src/actions/ModalActions.js index 25bebdfc..ea2434d9 100644 --- a/src/actions/ModalActions.js +++ b/src/actions/ModalActions.js @@ -112,6 +112,17 @@ export const onDeviceConnect = (device: Device): ThunkAction => (dispatch: Dispa } }; +export const onWalletTypeRequest = (device: TrezorDevice, hidden: boolean): ThunkAction => (dispatch: Dispatch): void => { + dispatch({ + type: MODAL.CLOSE, + }); + dispatch({ + type: CONNECT.RECEIVE_WALLET_TYPE, + device, + hidden, + }); +}; + export default { onPinSubmit, onPassphraseSubmit, @@ -121,4 +132,5 @@ export default { onForgetSingleDevice, onCancel, onDuplicateDevice, + onWalletTypeRequest, }; \ No newline at end of file diff --git a/src/components/modals/device/Type/index.js b/src/components/modals/device/Type/index.js new file mode 100644 index 00000000..3ea87286 --- /dev/null +++ b/src/components/modals/device/Type/index.js @@ -0,0 +1,70 @@ +/* @flow */ + +import React, { Component } from 'react'; +import styled from 'styled-components'; +import { H3 } from 'components/Heading'; +import P from 'components/Paragraph'; +import Button from 'components/Button'; + +import type { Props } from 'components/modals/index'; + +const Wrapper = styled.div` + width: 360px; + padding: 24px 48px; +`; + +const StyledButton = styled(Button)` + margin: 0 0 10px 0; +`; + +const Row = styled.div` + display: flex; + flex-direction: column; + padding: 10px 0; +`; + +class ForgetDevice extends Component { + + constructor(props: Props) { + super(props); + this.keyboardHandler = this.keyboardHandler.bind(this); + } + + componentDidMount() { + window.addEventListener('keydown', this.keyboardHandler, false); + } + + componentWillUnmount() { + window.removeEventListener('keydown', this.keyboardHandler, false); + } + + keyboardHandler(event: KeyboardEvent): void { + if (event.keyCode === 13) { + event.preventDefault(); + this.foo(false); + } + } + + keyboardHandler: (event: KeyboardEvent) => void; + + foo(hidden: boolean) { + this.props.modalActions.onWalletTypeRequest(this.props.modal.device, hidden); + } + + render() { + if (!this.props.modal.opened) return null; + const { device } = this.props.modal; + const { onCancel } = this.props.modalActions; + return ( + +

RequestWalletType for { device.instanceLabel }?

+ + this.foo(false)}>Basic + this.foo(true)}>Hidden + +
+ ); + } +} + +export default ForgetDevice; \ No newline at end of file diff --git a/src/components/modals/index.js b/src/components/modals/index.js index cb13f290..c78f7b3f 100644 --- a/src/components/modals/index.js +++ b/src/components/modals/index.js @@ -29,6 +29,7 @@ import ConfirmUnverifiedAddress from 'components/modals/confirm/UnverifiedAddres import ForgetDevice from 'components/modals/device/Forget'; import RememberDevice from 'components/modals/device/Remember'; import DuplicateDevice from 'components/modals/device/Duplicate'; +import RequestWalletType from 'components/modals/device/Type'; type OwnProps = { } @@ -123,6 +124,10 @@ class Modal extends Component { component = (); break; + case CONNECT.REQUEST_WALLET_TYPE: + component = (); + break; + default: component = null; } diff --git a/src/reducers/ModalReducer.js b/src/reducers/ModalReducer.js index 49b8bc07..8cfde96d 100644 --- a/src/reducers/ModalReducer.js +++ b/src/reducers/ModalReducer.js @@ -32,6 +32,13 @@ export default function modal(state: State = initialState, action: Action): Stat windowType: action.type, }; + case CONNECT.REQUEST_WALLET_TYPE: + return { + opened: true, + device: action.device, + windowType: action.type, + }; + case CONNECT.REMEMBER_REQUEST: return { opened: true, From 5c9194e814f1e24b51edc8a299b72046559d2cba Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 17:49:51 +0200 Subject: [PATCH 05/20] fixed flowtype in modals --- src/components/modals/device/Type/index.js | 6 ++++-- src/components/modals/passphrase/Type/index.js | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/modals/device/Type/index.js b/src/components/modals/device/Type/index.js index 3ea87286..e9676ac3 100644 --- a/src/components/modals/device/Type/index.js +++ b/src/components/modals/device/Type/index.js @@ -48,13 +48,15 @@ class ForgetDevice extends Component { keyboardHandler: (event: KeyboardEvent) => void; foo(hidden: boolean) { - this.props.modalActions.onWalletTypeRequest(this.props.modal.device, hidden); + const { modal } = this.props; + if (!modal.opened) return; + this.props.modalActions.onWalletTypeRequest(modal.device, hidden); } render() { if (!this.props.modal.opened) return null; const { device } = this.props.modal; - const { onCancel } = this.props.modalActions; + // const { onCancel } = this.props.modalActions; return (

RequestWalletType for { device.instanceLabel }?

diff --git a/src/components/modals/passphrase/Type/index.js b/src/components/modals/passphrase/Type/index.js index 568c1c3d..7ce9951c 100644 --- a/src/components/modals/passphrase/Type/index.js +++ b/src/components/modals/passphrase/Type/index.js @@ -1,9 +1,14 @@ +/* @flow */ + import React from 'react'; import Icon from 'components/Icon'; import colors from 'config/colors'; import icons from 'config/icons'; import styled from 'styled-components'; import { H3 } from 'components/Heading'; +import P from 'components/Paragraph'; + +import type { Props } from 'components/modals/index'; const Wrapper = styled.div` width: 360px; @@ -12,7 +17,7 @@ const Wrapper = styled.div` const Header = styled.div``; -const Confirmation = (props) => { +const Confirmation = (props: Props) => { if (!props.modal.opened) return null; const { device } = props.modal; @@ -21,6 +26,7 @@ const Confirmation = (props) => {

Complete the action on { device.label } device

+

TODO: add detailed text here. Explain passphrase/hidden wallet...

); From 25d95a971f51e7d7cafae01c71bd20fcbe99a62a Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 17:55:26 +0200 Subject: [PATCH 06/20] FORGET_SILENT if disconnected device is not selected and modal is opened --- src/actions/TrezorConnectActions.js | 35 +++++++++++++------------- src/actions/constants/TrezorConnect.js | 1 + src/reducers/DevicesReducer.js | 2 ++ 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index 8f0bd2e8..c5928afa 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -6,6 +6,7 @@ import * as CONNECT from 'actions/constants/TrezorConnect'; import * as NOTIFICATION from 'actions/constants/notification'; import { getDuplicateInstanceNumber } from 'reducers/utils'; import * as RouterActions from 'actions/RouterActions'; +import * as deviceUtils from 'utils/device'; import type { DeviceMessage, @@ -58,7 +59,7 @@ export type TrezorConnectAction = { type: typeof CONNECT.FORGET, device: TrezorDevice } | { - type: typeof CONNECT.FORGET_SINGLE, + type: typeof CONNECT.FORGET_SINGLE | typeof CONNECT.FORGET_SILENT, device: TrezorDevice } | { type: typeof CONNECT.REMEMBER, @@ -222,11 +223,19 @@ export const deviceDisconnect = (device: Device): AsyncAction => async (dispatch if (device.features) { const instances = getState().devices.filter(d => d.features && device.features && d.state && !d.remember && d.features.device_id === device.features.device_id); if (instances.length > 0) { - dispatch({ - type: CONNECT.REMEMBER_REQUEST, - device: instances[0], - instances, - }); + const isSelected = deviceUtils.isSelectedDevice(getState().wallet.selectedDevice, instances[0]); + if (!isSelected && getState().modal.opened) { + dispatch({ + type: CONNECT.FORGET_SILENT, + device: instances[0], + }); + } else { + dispatch({ + type: CONNECT.REMEMBER_REQUEST, + device: instances[0], + instances, + }); + } } else { dispatch(RouterActions.selectFirstAvailableDevice()); } @@ -291,12 +300,7 @@ export const forget = (device: TrezorDevice): Action => ({ device, }); -export const duplicateDevice1 = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - // dispatch({ - // type: CONNECT.TRY_TO_DUPLICATE, - // device, - // }); - +export const duplicateDeviceOld = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { const instance: number = getDuplicateInstanceNumber(getState().devices, device); const extended: Object = { instance }; dispatch({ @@ -305,12 +309,7 @@ export const duplicateDevice1 = (device: TrezorDevice): AsyncAction => async (di }); }; -export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - // dispatch({ - // type: CONNECT.TRY_TO_DUPLICATE, - // device, - // }); - +export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch): Promise => { dispatch({ type: CONNECT.REQUEST_WALLET_TYPE, device, diff --git a/src/actions/constants/TrezorConnect.js b/src/actions/constants/TrezorConnect.js index 7a6a446d..2df229ee 100644 --- a/src/actions/constants/TrezorConnect.js +++ b/src/actions/constants/TrezorConnect.js @@ -16,6 +16,7 @@ export const REMEMBER_REQUEST: 'connect__remember_request' = 'connect__remember_ export const FORGET_REQUEST: 'connect__forget_request' = 'connect__forget_request'; export const FORGET: 'connect__forget' = 'connect__forget'; export const FORGET_SINGLE: 'connect__forget_single' = 'connect__forget_single'; +export const FORGET_SILENT: 'connect__forget_silent' = 'connect__forget_silent'; export const DISCONNECT_REQUEST: 'connect__disconnect_request' = 'connect__disconnect_request'; export const REMEMBER: 'connect__remember' = 'connect__remember'; diff --git a/src/reducers/DevicesReducer.js b/src/reducers/DevicesReducer.js index e55b951c..a6ba5fc0 100644 --- a/src/reducers/DevicesReducer.js +++ b/src/reducers/DevicesReducer.js @@ -271,6 +271,7 @@ const onChangeWalletType = (state: State, device: TrezorDevice, hidden: boolean) ...d, state: null, useEmptyPassphrase: !hidden, + ts: new Date().getTime(), } : d; }); return otherDevices.concat(changedDevices); @@ -296,6 +297,7 @@ export default function devices(state: State = initialState, action: Action): St case CONNECT.FORGET: return forgetDevice(state, action.device); case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: return forgetSingleDevice(state, action.device); case DEVICE.CONNECT: From 286caf9d2951c2d1003838c72a9aea85d2fa8936 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 11:59:10 +0200 Subject: [PATCH 07/20] remove data while switchin between wallet types --- src/reducers/AccountsReducer.js | 2 ++ src/reducers/DiscoveryReducer.js | 2 ++ src/reducers/TokensReducer.js | 2 ++ src/services/LocalStorageService.js | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/reducers/AccountsReducer.js b/src/reducers/AccountsReducer.js index 3e605191..48883d61 100644 --- a/src/reducers/AccountsReducer.js +++ b/src/reducers/AccountsReducer.js @@ -92,6 +92,8 @@ export default (state: State = initialState, action: Action): State => { case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: return removeAccounts(state, action.device); case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA: diff --git a/src/reducers/DiscoveryReducer.js b/src/reducers/DiscoveryReducer.js index c6712b50..28294b2d 100644 --- a/src/reducers/DiscoveryReducer.js +++ b/src/reducers/DiscoveryReducer.js @@ -185,6 +185,8 @@ export default function discovery(state: State = initialState, action: Action): }); case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: return forgetDiscovery(state, action.device); case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA: return clear(state, action.devices); diff --git a/src/reducers/TokensReducer.js b/src/reducers/TokensReducer.js index 6c6455c7..c880c588 100644 --- a/src/reducers/TokensReducer.js +++ b/src/reducers/TokensReducer.js @@ -71,6 +71,8 @@ export default (state: State = initialState, action: Action): State => { case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: return forget(state, action.device); case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA: diff --git a/src/services/LocalStorageService.js b/src/services/LocalStorageService.js index 9a9af858..b98fbf62 100644 --- a/src/services/LocalStorageService.js +++ b/src/services/LocalStorageService.js @@ -102,6 +102,8 @@ const LocalStorageService: Middleware = (api: MiddlewareAPI) => (next: Middlewar case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: case DEVICE.CHANGED: case DEVICE.DISCONNECT: case CONNECT.AUTH_DEVICE: From 109c93aff8353aa936521bd14b554c9dd38c7ff2 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 15:31:03 +0200 Subject: [PATCH 08/20] added new field "useEmptyPassphrase" to TrezorDevice object --- src/flowtype/index.js | 2 ++ src/reducers/DevicesReducer.js | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/flowtype/index.js b/src/flowtype/index.js index 203033d1..44bd5556 100644 --- a/src/flowtype/index.js +++ b/src/flowtype/index.js @@ -56,6 +56,7 @@ export type AcquiredDevice = $Exact<{ status: DeviceStatus, +mode: DeviceMode, state: ?string, + useEmptyPassphrase: boolean, remember: boolean; // device should be remembered connected: boolean; // device is connected @@ -73,6 +74,7 @@ export type UnknownDevice = $Exact<{ +label: string, +features: null, state: ?string, + useEmptyPassphrase: boolean, remember: boolean; // device should be remembered connected: boolean; // device is connected diff --git a/src/reducers/DevicesReducer.js b/src/reducers/DevicesReducer.js index 81f2b4b1..e55b951c 100644 --- a/src/reducers/DevicesReducer.js +++ b/src/reducers/DevicesReducer.js @@ -39,6 +39,7 @@ const mergeDevices = (current: TrezorDevice, upcoming: Device | TrezorDevice): T instanceName: typeof upcoming.instanceName === 'string' ? upcoming.instanceName : current.instanceName, state: current.state, ts: typeof upcoming.ts === 'number' ? upcoming.ts : current.ts, + useEmptyPassphrase: typeof upcoming.useEmptyPassphrase === 'boolean' ? upcoming.useEmptyPassphrase : current.useEmptyPassphrase, }; if (upcoming.type === 'acquired') { @@ -89,6 +90,7 @@ const addDevice = (state: State, device: Device): State => { instanceLabel: device.label, instanceName: null, ts: new Date().getTime(), + useEmptyPassphrase: true, }; @@ -260,6 +262,22 @@ const onSelectedDevice = (state: State, device: ?TrezorDevice): State => { return otherDevices.concat([extended]); }; +const onChangeWalletType = (state: State, device: TrezorDevice, hidden: boolean): State => { + const affectedDevices: State = state.filter(d => d.path === device.path || (d.features && device.features && d.features.device_id === device.features.device_id)); + const otherDevices: State = state.filter(d => affectedDevices.indexOf(d) === -1); + if (affectedDevices.length > 0) { + const changedDevices = affectedDevices.map((d) => { // eslint-disable-line arrow-body-style + return d.type === 'acquired' ? { + ...d, + state: null, + useEmptyPassphrase: !hidden, + } : d; + }); + return otherDevices.concat(changedDevices); + } + return state; +}; + export default function devices(state: State = initialState, action: Action): State { switch (action.type) { case CONNECT.DEVICE_FROM_STORAGE: @@ -296,6 +314,9 @@ export default function devices(state: State = initialState, action: Action): St case WALLET.SET_SELECTED_DEVICE: return onSelectedDevice(state, action.device); + case CONNECT.RECEIVE_WALLET_TYPE: + return onChangeWalletType(state, action.device, action.hidden); + default: return state; } From 31834261373c697dced789d428aaeadf39204c0e Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 15:46:47 +0200 Subject: [PATCH 09/20] TrezorConnect calls using new field "useEmptyPassphrase" --- src/actions/DiscoveryActions.js | 6 ++++-- src/actions/ReceiveActions.js | 3 ++- src/actions/SendFormActions.js | 3 ++- .../components/DeviceMenu/components/MenuItems/index.js | 6 +++--- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index e9c02369..596bc335 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -142,7 +142,8 @@ const begin = (device: TrezorDevice, network: string): AsyncAction => async (dis }, path: coinToDiscover.bip44, keepSession: true, // acquire and hold session - useEmptyPassphrase: !device.instance, + //useEmptyPassphrase: !device.instance, + useEmptyPassphrase: device.useEmptyPassphrase, }); // handle TREZOR response error @@ -264,7 +265,8 @@ const finish = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction state: device.state, }, keepSession: false, - useEmptyPassphrase: !device.instance, + // useEmptyPassphrase: !device.instance, + useEmptyPassphrase: device.useEmptyPassphrase, }); await dispatch(BlockchainActions.subscribe(discoveryProcess.network)); diff --git a/src/actions/ReceiveActions.js b/src/actions/ReceiveActions.js index 6f193e48..95d56119 100644 --- a/src/actions/ReceiveActions.js +++ b/src/actions/ReceiveActions.js @@ -67,7 +67,8 @@ export const showAddress = (path: Array): AsyncAction => async (dispatch state: selected.state, }, path, - useEmptyPassphrase: !selected.instance, + // useEmptyPassphrase: !selected.instance, + useEmptyPassphrase: selected.useEmptyPassphrase, }); if (response && response.success) { diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index f26664f3..90ddf02e 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -458,7 +458,8 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge instance: selected.instance, state: selected.state, }, - useEmptyPassphrase: !selected.instance, + // useEmptyPassphrase: !selected.instance, + useEmptyPassphrase: selected.useEmptyPassphrase, path: account.addressPath, transaction: txData, }); diff --git a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/components/MenuItems/index.js b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/components/MenuItems/index.js index a52bb769..969d3363 100644 --- a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/components/MenuItems/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/components/MenuItems/index.js @@ -58,14 +58,14 @@ class MenuItems extends Component { if (!this.showDeviceMenu()) return null; return ( - this.onDeviceMenuClick('settings', this.props.device)}> + {/* this.onDeviceMenuClick('settings', this.props.device)}> - + */} this.onDeviceMenuClick('forget', this.props.device)}> - + )} {this.showRenewSession() && ( From 291e771a6bbc5aa27eefaa81f1a26b4c0cea351a Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 15:47:37 +0200 Subject: [PATCH 10/20] new actions: request and receive wallet type --- src/actions/TrezorConnectActions.js | 45 ++++++++++++++++++++++---- src/actions/WalletActions.js | 1 + src/actions/constants/TrezorConnect.js | 5 ++- src/services/WalletService.js | 23 ++++++++----- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index b54a97a0..8f0bd2e8 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -71,6 +71,13 @@ export type TrezorConnectAction = { payload: Array } | { type: typeof CONNECT.START_ACQUIRING | typeof CONNECT.STOP_ACQUIRING, +} | { + type: typeof CONNECT.REQUEST_WALLET_TYPE, + device: TrezorDevice +} | { + type: typeof CONNECT.RECEIVE_WALLET_TYPE, + device: TrezorDevice, + hidden: boolean, }; export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { @@ -152,7 +159,19 @@ export const postInit = (): ThunkAction => (dispatch: Dispatch): void => { } }; -export const getSelectedDeviceState = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const requestWalletType = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const selected = getState().wallet.selectedDevice; + if (!selected) return; + const isDeviceReady = selected.connected && selected.features && !selected.state && selected.mode === 'normal' && selected.firmware !== 'required'; + if (!isDeviceReady) return; + + dispatch({ + type: CONNECT.REQUEST_WALLET_TYPE, + device: selected, + }); +}; + +export const authorizeDevice = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { const selected = getState().wallet.selectedDevice; if (!selected) return; const isDeviceReady = selected.connected && selected.features && !selected.state && selected.mode === 'normal' && selected.firmware !== 'required'; @@ -164,7 +183,7 @@ export const getSelectedDeviceState = (): AsyncAction => async (dispatch: Dispat instance: selected.instance, state: selected.state, }, - useEmptyPassphrase: !selected.instance, + useEmptyPassphrase: selected.useEmptyPassphrase, }); if (response && response.success) { @@ -190,14 +209,13 @@ export const getSelectedDeviceState = (): AsyncAction => async (dispatch: Dispat type: NOTIFICATION.CLOSE, payload: { devicePath: selected.path }, }); - dispatch(getSelectedDeviceState()); + dispatch(authorizeDevice()); }, }, ], }, }); } - }; export const deviceDisconnect = (device: Device): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { @@ -231,11 +249,14 @@ export function acquire(): AsyncAction { type: CONNECT.START_ACQUIRING, }); + // this is the only place where useEmptyPassphrase should be used every time + // the goal here is to acquire device and get his features + // authentication (passphrase) is not needed here yet const response = await TrezorConnect.getFeatures({ device: { path: selected.path, }, - useEmptyPassphrase: !selected.instance, + useEmptyPassphrase: true, }); if (!response.success) { @@ -270,7 +291,7 @@ export const forget = (device: TrezorDevice): Action => ({ device, }); -export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const duplicateDevice1 = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { // dispatch({ // type: CONNECT.TRY_TO_DUPLICATE, // device, @@ -283,3 +304,15 @@ export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dis device: { ...device, ...extended }, }); }; + +export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { + // dispatch({ + // type: CONNECT.TRY_TO_DUPLICATE, + // device, + // }); + + dispatch({ + type: CONNECT.REQUEST_WALLET_TYPE, + device, + }); +}; diff --git a/src/actions/WalletActions.js b/src/actions/WalletActions.js index a7325d25..b477ce14 100644 --- a/src/actions/WalletActions.js +++ b/src/actions/WalletActions.js @@ -87,6 +87,7 @@ export const clearUnavailableDevicesData = (prevState: State, device: Device): T const actions = [ LOCATION_CHANGE, CONNECT.AUTH_DEVICE, + CONNECT.RECEIVE_WALLET_TYPE, ...Object.values(DEVICE).filter(v => typeof v === 'string'), ]; diff --git a/src/actions/constants/TrezorConnect.js b/src/actions/constants/TrezorConnect.js index a49371c5..7a6a446d 100644 --- a/src/actions/constants/TrezorConnect.js +++ b/src/actions/constants/TrezorConnect.js @@ -25,4 +25,7 @@ export const DUPLICATE: 'connect__duplicate' = 'connect__duplicate'; export const DEVICE_STATE_EXCEPTION: 'connect__device_state_exception' = 'connect__device_state_exception'; export const START_ACQUIRING: 'connect__start_acquiring' = 'connect__start_acquiring'; -export const STOP_ACQUIRING: 'connect__stop_acquiring' = 'connect__stop_acquiring'; \ No newline at end of file +export const STOP_ACQUIRING: 'connect__stop_acquiring' = 'connect__stop_acquiring'; + +export const REQUEST_WALLET_TYPE: 'connect__request_wallet_type' = 'connect__request_wallet_type'; +export const RECEIVE_WALLET_TYPE: 'connect__receive_wallet_type' = 'connect__receive_wallet_type'; \ No newline at end of file diff --git a/src/services/WalletService.js b/src/services/WalletService.js index 3cfe4ddb..0e2b87d2 100644 --- a/src/services/WalletService.js +++ b/src/services/WalletService.js @@ -49,10 +49,9 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa api.dispatch(LocalStorageActions.loadData()); break; case WALLET.SET_SELECTED_DEVICE: - if (action.device) { - // try to authorize device - api.dispatch(TrezorConnectActions.getSelectedDeviceState()); - } + // try to authorize device + // api.dispatch(TrezorConnectActions.authorizeDevice()); + api.dispatch(TrezorConnectActions.requestWalletType()); break; case DEVICE.CONNECT: api.dispatch(WalletActions.clearUnavailableDevicesData(prevState, action.device)); @@ -102,10 +101,18 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa // if "selectedAccount" didn't change observe send form props changes api.dispatch(SendFormActionActions.observe(prevState, action)); } - } else if (action.type === CONNECT.AUTH_DEVICE) { - // selected device did changed - // try to restore discovery after device authentication - api.dispatch(DiscoveryActions.restore()); + } else { + switch (action.type) { + case CONNECT.AUTH_DEVICE: + // selected device did changed + // try to restore discovery after device authentication + api.dispatch(DiscoveryActions.restore()); + break; + case CONNECT.RECEIVE_WALLET_TYPE: + api.dispatch(TrezorConnectActions.authorizeDevice()); + break; + default: break; + } } // even if "selectedDevice" didn't change because it was updated on DEVICE.CHANGED before DEVICE.CONNECT action From cea3fe7e68857f7aa9b2beae958b6006fa299f13 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 15:47:51 +0200 Subject: [PATCH 11/20] new modal "wallet type" --- src/actions/ModalActions.js | 12 ++++ src/components/modals/device/Type/index.js | 70 ++++++++++++++++++++++ src/components/modals/index.js | 5 ++ src/reducers/ModalReducer.js | 7 +++ 4 files changed, 94 insertions(+) create mode 100644 src/components/modals/device/Type/index.js diff --git a/src/actions/ModalActions.js b/src/actions/ModalActions.js index 25bebdfc..ea2434d9 100644 --- a/src/actions/ModalActions.js +++ b/src/actions/ModalActions.js @@ -112,6 +112,17 @@ export const onDeviceConnect = (device: Device): ThunkAction => (dispatch: Dispa } }; +export const onWalletTypeRequest = (device: TrezorDevice, hidden: boolean): ThunkAction => (dispatch: Dispatch): void => { + dispatch({ + type: MODAL.CLOSE, + }); + dispatch({ + type: CONNECT.RECEIVE_WALLET_TYPE, + device, + hidden, + }); +}; + export default { onPinSubmit, onPassphraseSubmit, @@ -121,4 +132,5 @@ export default { onForgetSingleDevice, onCancel, onDuplicateDevice, + onWalletTypeRequest, }; \ No newline at end of file diff --git a/src/components/modals/device/Type/index.js b/src/components/modals/device/Type/index.js new file mode 100644 index 00000000..3ea87286 --- /dev/null +++ b/src/components/modals/device/Type/index.js @@ -0,0 +1,70 @@ +/* @flow */ + +import React, { Component } from 'react'; +import styled from 'styled-components'; +import { H3 } from 'components/Heading'; +import P from 'components/Paragraph'; +import Button from 'components/Button'; + +import type { Props } from 'components/modals/index'; + +const Wrapper = styled.div` + width: 360px; + padding: 24px 48px; +`; + +const StyledButton = styled(Button)` + margin: 0 0 10px 0; +`; + +const Row = styled.div` + display: flex; + flex-direction: column; + padding: 10px 0; +`; + +class ForgetDevice extends Component { + + constructor(props: Props) { + super(props); + this.keyboardHandler = this.keyboardHandler.bind(this); + } + + componentDidMount() { + window.addEventListener('keydown', this.keyboardHandler, false); + } + + componentWillUnmount() { + window.removeEventListener('keydown', this.keyboardHandler, false); + } + + keyboardHandler(event: KeyboardEvent): void { + if (event.keyCode === 13) { + event.preventDefault(); + this.foo(false); + } + } + + keyboardHandler: (event: KeyboardEvent) => void; + + foo(hidden: boolean) { + this.props.modalActions.onWalletTypeRequest(this.props.modal.device, hidden); + } + + render() { + if (!this.props.modal.opened) return null; + const { device } = this.props.modal; + const { onCancel } = this.props.modalActions; + return ( + +

RequestWalletType for { device.instanceLabel }?

+ + this.foo(false)}>Basic + this.foo(true)}>Hidden + +
+ ); + } +} + +export default ForgetDevice; \ No newline at end of file diff --git a/src/components/modals/index.js b/src/components/modals/index.js index cb13f290..c78f7b3f 100644 --- a/src/components/modals/index.js +++ b/src/components/modals/index.js @@ -29,6 +29,7 @@ import ConfirmUnverifiedAddress from 'components/modals/confirm/UnverifiedAddres import ForgetDevice from 'components/modals/device/Forget'; import RememberDevice from 'components/modals/device/Remember'; import DuplicateDevice from 'components/modals/device/Duplicate'; +import RequestWalletType from 'components/modals/device/Type'; type OwnProps = { } @@ -123,6 +124,10 @@ class Modal extends Component { component = (); break; + case CONNECT.REQUEST_WALLET_TYPE: + component = (); + break; + default: component = null; } diff --git a/src/reducers/ModalReducer.js b/src/reducers/ModalReducer.js index 49b8bc07..8cfde96d 100644 --- a/src/reducers/ModalReducer.js +++ b/src/reducers/ModalReducer.js @@ -32,6 +32,13 @@ export default function modal(state: State = initialState, action: Action): Stat windowType: action.type, }; + case CONNECT.REQUEST_WALLET_TYPE: + return { + opened: true, + device: action.device, + windowType: action.type, + }; + case CONNECT.REMEMBER_REQUEST: return { opened: true, From a357c7dc8c597becf4bf5e866d5fa114118dd1b1 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 17:49:51 +0200 Subject: [PATCH 12/20] fixed flowtype in modals --- src/components/modals/device/Type/index.js | 6 ++++-- src/components/modals/passphrase/Type/index.js | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/modals/device/Type/index.js b/src/components/modals/device/Type/index.js index 3ea87286..e9676ac3 100644 --- a/src/components/modals/device/Type/index.js +++ b/src/components/modals/device/Type/index.js @@ -48,13 +48,15 @@ class ForgetDevice extends Component { keyboardHandler: (event: KeyboardEvent) => void; foo(hidden: boolean) { - this.props.modalActions.onWalletTypeRequest(this.props.modal.device, hidden); + const { modal } = this.props; + if (!modal.opened) return; + this.props.modalActions.onWalletTypeRequest(modal.device, hidden); } render() { if (!this.props.modal.opened) return null; const { device } = this.props.modal; - const { onCancel } = this.props.modalActions; + // const { onCancel } = this.props.modalActions; return (

RequestWalletType for { device.instanceLabel }?

diff --git a/src/components/modals/passphrase/Type/index.js b/src/components/modals/passphrase/Type/index.js index 568c1c3d..7ce9951c 100644 --- a/src/components/modals/passphrase/Type/index.js +++ b/src/components/modals/passphrase/Type/index.js @@ -1,9 +1,14 @@ +/* @flow */ + import React from 'react'; import Icon from 'components/Icon'; import colors from 'config/colors'; import icons from 'config/icons'; import styled from 'styled-components'; import { H3 } from 'components/Heading'; +import P from 'components/Paragraph'; + +import type { Props } from 'components/modals/index'; const Wrapper = styled.div` width: 360px; @@ -12,7 +17,7 @@ const Wrapper = styled.div` const Header = styled.div``; -const Confirmation = (props) => { +const Confirmation = (props: Props) => { if (!props.modal.opened) return null; const { device } = props.modal; @@ -21,6 +26,7 @@ const Confirmation = (props) => {

Complete the action on { device.label } device

+

TODO: add detailed text here. Explain passphrase/hidden wallet...

); From 14eac38246ffc3b3c13acf5ca4517484e690e15a Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 5 Oct 2018 17:55:26 +0200 Subject: [PATCH 13/20] FORGET_SILENT if disconnected device is not selected and modal is opened --- src/actions/TrezorConnectActions.js | 35 +++++++++++++------------- src/actions/constants/TrezorConnect.js | 1 + src/reducers/DevicesReducer.js | 2 ++ 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index 8f0bd2e8..c5928afa 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -6,6 +6,7 @@ import * as CONNECT from 'actions/constants/TrezorConnect'; import * as NOTIFICATION from 'actions/constants/notification'; import { getDuplicateInstanceNumber } from 'reducers/utils'; import * as RouterActions from 'actions/RouterActions'; +import * as deviceUtils from 'utils/device'; import type { DeviceMessage, @@ -58,7 +59,7 @@ export type TrezorConnectAction = { type: typeof CONNECT.FORGET, device: TrezorDevice } | { - type: typeof CONNECT.FORGET_SINGLE, + type: typeof CONNECT.FORGET_SINGLE | typeof CONNECT.FORGET_SILENT, device: TrezorDevice } | { type: typeof CONNECT.REMEMBER, @@ -222,11 +223,19 @@ export const deviceDisconnect = (device: Device): AsyncAction => async (dispatch if (device.features) { const instances = getState().devices.filter(d => d.features && device.features && d.state && !d.remember && d.features.device_id === device.features.device_id); if (instances.length > 0) { - dispatch({ - type: CONNECT.REMEMBER_REQUEST, - device: instances[0], - instances, - }); + const isSelected = deviceUtils.isSelectedDevice(getState().wallet.selectedDevice, instances[0]); + if (!isSelected && getState().modal.opened) { + dispatch({ + type: CONNECT.FORGET_SILENT, + device: instances[0], + }); + } else { + dispatch({ + type: CONNECT.REMEMBER_REQUEST, + device: instances[0], + instances, + }); + } } else { dispatch(RouterActions.selectFirstAvailableDevice()); } @@ -291,12 +300,7 @@ export const forget = (device: TrezorDevice): Action => ({ device, }); -export const duplicateDevice1 = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - // dispatch({ - // type: CONNECT.TRY_TO_DUPLICATE, - // device, - // }); - +export const duplicateDeviceOld = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { const instance: number = getDuplicateInstanceNumber(getState().devices, device); const extended: Object = { instance }; dispatch({ @@ -305,12 +309,7 @@ export const duplicateDevice1 = (device: TrezorDevice): AsyncAction => async (di }); }; -export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - // dispatch({ - // type: CONNECT.TRY_TO_DUPLICATE, - // device, - // }); - +export const duplicateDevice = (device: TrezorDevice): AsyncAction => async (dispatch: Dispatch): Promise => { dispatch({ type: CONNECT.REQUEST_WALLET_TYPE, device, diff --git a/src/actions/constants/TrezorConnect.js b/src/actions/constants/TrezorConnect.js index 7a6a446d..2df229ee 100644 --- a/src/actions/constants/TrezorConnect.js +++ b/src/actions/constants/TrezorConnect.js @@ -16,6 +16,7 @@ export const REMEMBER_REQUEST: 'connect__remember_request' = 'connect__remember_ export const FORGET_REQUEST: 'connect__forget_request' = 'connect__forget_request'; export const FORGET: 'connect__forget' = 'connect__forget'; export const FORGET_SINGLE: 'connect__forget_single' = 'connect__forget_single'; +export const FORGET_SILENT: 'connect__forget_silent' = 'connect__forget_silent'; export const DISCONNECT_REQUEST: 'connect__disconnect_request' = 'connect__disconnect_request'; export const REMEMBER: 'connect__remember' = 'connect__remember'; diff --git a/src/reducers/DevicesReducer.js b/src/reducers/DevicesReducer.js index e55b951c..a6ba5fc0 100644 --- a/src/reducers/DevicesReducer.js +++ b/src/reducers/DevicesReducer.js @@ -271,6 +271,7 @@ const onChangeWalletType = (state: State, device: TrezorDevice, hidden: boolean) ...d, state: null, useEmptyPassphrase: !hidden, + ts: new Date().getTime(), } : d; }); return otherDevices.concat(changedDevices); @@ -296,6 +297,7 @@ export default function devices(state: State = initialState, action: Action): St case CONNECT.FORGET: return forgetDevice(state, action.device); case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: return forgetSingleDevice(state, action.device); case DEVICE.CONNECT: From 0a77d0541e85f98a83106a84048e9c0486ec0338 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 11:59:10 +0200 Subject: [PATCH 14/20] remove data while switchin between wallet types --- src/reducers/AccountsReducer.js | 2 ++ src/reducers/DiscoveryReducer.js | 2 ++ src/reducers/TokensReducer.js | 2 ++ src/services/LocalStorageService.js | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/reducers/AccountsReducer.js b/src/reducers/AccountsReducer.js index 3e605191..48883d61 100644 --- a/src/reducers/AccountsReducer.js +++ b/src/reducers/AccountsReducer.js @@ -92,6 +92,8 @@ export default (state: State = initialState, action: Action): State => { case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: return removeAccounts(state, action.device); case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA: diff --git a/src/reducers/DiscoveryReducer.js b/src/reducers/DiscoveryReducer.js index c6712b50..28294b2d 100644 --- a/src/reducers/DiscoveryReducer.js +++ b/src/reducers/DiscoveryReducer.js @@ -185,6 +185,8 @@ export default function discovery(state: State = initialState, action: Action): }); case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: return forgetDiscovery(state, action.device); case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA: return clear(state, action.devices); diff --git a/src/reducers/TokensReducer.js b/src/reducers/TokensReducer.js index 6c6455c7..c880c588 100644 --- a/src/reducers/TokensReducer.js +++ b/src/reducers/TokensReducer.js @@ -71,6 +71,8 @@ export default (state: State = initialState, action: Action): State => { case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: return forget(state, action.device); case WALLET.CLEAR_UNAVAILABLE_DEVICE_DATA: diff --git a/src/services/LocalStorageService.js b/src/services/LocalStorageService.js index 9a9af858..b98fbf62 100644 --- a/src/services/LocalStorageService.js +++ b/src/services/LocalStorageService.js @@ -102,6 +102,8 @@ const LocalStorageService: Middleware = (api: MiddlewareAPI) => (next: Middlewar case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: case DEVICE.CHANGED: case DEVICE.DISCONNECT: case CONNECT.AUTH_DEVICE: From d6af3d6dfa8eee6639d7cbe39ddef7f632089aab Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 12:17:31 +0200 Subject: [PATCH 15/20] remove pendingTxs while switching between wallet types and forgeting device --- src/actions/PendingTxActions.js | 31 +------------------------------ src/reducers/PendingTxReducer.js | 20 ++++++++++++++++---- 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/src/actions/PendingTxActions.js b/src/actions/PendingTxActions.js index a6377171..fd9e3763 100644 --- a/src/actions/PendingTxActions.js +++ b/src/actions/PendingTxActions.js @@ -3,12 +3,8 @@ import * as PENDING from 'actions/constants/pendingTx'; -import type { - Action, ThunkAction, GetState, Dispatch, -} from 'flowtype'; import type { State, PendingTx } from 'reducers/PendingTxReducer'; - export type PendingTxAction = { type: typeof PENDING.FROM_STORAGE, payload: State @@ -25,29 +21,4 @@ export type PendingTxAction = { } | { type: typeof PENDING.TX_TOKEN_ERROR, tx: PendingTx, -} - -export const reject = (tx: PendingTx): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { - /* - dispatch({ - type: NOTIFICATION.ADD, - payload: { - type: 'warning', - title: 'Pending transaction rejected', - message: `Transaction with id: ${tx.id} not found.`, - cancelable: true, - actions: [ - { - label: 'OK', - callback: () => { - dispatch({ - type: PENDING.TX_RESOLVED, - tx, - }); - }, - }, - ], - }, - }); - */ -}; \ No newline at end of file +} \ No newline at end of file diff --git a/src/reducers/PendingTxReducer.js b/src/reducers/PendingTxReducer.js index f89243ea..7493c4c9 100644 --- a/src/reducers/PendingTxReducer.js +++ b/src/reducers/PendingTxReducer.js @@ -1,20 +1,22 @@ /* @flow */ +import * as CONNECT from 'actions/constants/TrezorConnect'; import * as PENDING from 'actions/constants/pendingTx'; import * as SEND from 'actions/constants/send'; -import type { Action } from 'flowtype'; +import type { TrezorDevice, Action } from 'flowtype'; import type { SendTxAction } from 'actions/SendFormActions'; export type PendingTx = { - +type: 'send' | 'recv'; + +type: 'send' | 'receive'; +id: string; +network: string; + +address: string; + +deviceState: string; +currency: string; +amount: string; +total: string; +tx: any; +nonce: number; - +address: string; rejected: boolean; } @@ -28,12 +30,14 @@ const add = (state: State, action: SendTxAction): State => { type: 'send', id: action.txid, network: action.account.network, + address: action.account.address, + deviceState: action.account.deviceState, + currency: action.selectedCurrency, amount: action.amount, total: action.total, tx: action.tx, nonce: action.nonce, - address: action.account.address, rejected: false, }); return newState; @@ -47,6 +51,8 @@ const addFromBloockbokNotifiaction = (state: State, payload: any): State => { }; */ +const clear = (state: State, device: TrezorDevice): State => state.filter(tx => tx.deviceState !== device.state); + const remove = (state: State, id: string): State => state.filter(tx => tx.id !== id); const reject = (state: State, id: string): State => state.map((tx) => { @@ -61,6 +67,12 @@ export default function pending(state: State = initialState, action: Action): St case SEND.TX_COMPLETE: return add(state, action); + case CONNECT.FORGET: + case CONNECT.FORGET_SINGLE: + case CONNECT.FORGET_SILENT: + case CONNECT.RECEIVE_WALLET_TYPE: + return clear(state, action.device); + // case PENDING.ADD: // return add(state, action.payload); case PENDING.TX_RESOLVED: From d8331cece0368720accc2c6749d230681589075f Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 12:28:30 +0200 Subject: [PATCH 16/20] reset "remember" field while switching wallet type --- src/reducers/DevicesReducer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/reducers/DevicesReducer.js b/src/reducers/DevicesReducer.js index a6ba5fc0..0ed79b82 100644 --- a/src/reducers/DevicesReducer.js +++ b/src/reducers/DevicesReducer.js @@ -269,6 +269,7 @@ const onChangeWalletType = (state: State, device: TrezorDevice, hidden: boolean) const changedDevices = affectedDevices.map((d) => { // eslint-disable-line arrow-body-style return d.type === 'acquired' ? { ...d, + remember: false, state: null, useEmptyPassphrase: !hidden, ts: new Date().getTime(), From 1a55f45d2d3b977c2f90695b4d33821c6648698e Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 15:52:24 +0200 Subject: [PATCH 17/20] goto to dashboard page when switching wallet type --- src/actions/RouterActions.js | 4 ++-- src/services/WalletService.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/actions/RouterActions.js b/src/actions/RouterActions.js index e1101652..c5cd20c1 100644 --- a/src/actions/RouterActions.js +++ b/src/actions/RouterActions.js @@ -258,12 +258,12 @@ export const selectDevice = (device: TrezorDevice | Device): ThunkAction => (dis /* * Redirect to first device or landing page */ -export const selectFirstAvailableDevice = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { +export const selectFirstAvailableDevice = (gotoRoot: boolean = false): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { const url = dispatch(getFirstAvailableDeviceUrl()); if (url) { const currentParams = getState().router.location.state; const requestedParams = dispatch(pathToParams(url)); - if (currentParams.device !== requestedParams.device || currentParams.deviceInstance !== requestedParams.deviceInstance) { + if (gotoRoot || currentParams.device !== requestedParams.device || currentParams.deviceInstance !== requestedParams.deviceInstance) { dispatch(goto(url)); } } else { diff --git a/src/services/WalletService.js b/src/services/WalletService.js index 0e2b87d2..dac93767 100644 --- a/src/services/WalletService.js +++ b/src/services/WalletService.js @@ -11,6 +11,7 @@ import * as TrezorConnectActions from 'actions/TrezorConnectActions'; import * as SelectedAccountActions from 'actions/SelectedAccountActions'; import * as SendFormActionActions from 'actions/SendFormActions'; import * as DiscoveryActions from 'actions/DiscoveryActions'; +import * as RouterActions from 'actions/RouterActions'; import type { Middleware, @@ -109,6 +110,7 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa api.dispatch(DiscoveryActions.restore()); break; case CONNECT.RECEIVE_WALLET_TYPE: + api.dispatch(RouterActions.selectFirstAvailableDevice(true)); api.dispatch(TrezorConnectActions.authorizeDevice()); break; default: break; From e4bb6d5d475bf3ea793c063ce62bcbfe3b383e94 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 17:12:23 +0200 Subject: [PATCH 18/20] added texts for passphrase modals and wallet type icons --- src/components/images/WalletType/index.js | 51 +++++++++++++++++++ src/components/modals/device/Type/index.js | 39 +++++++++++--- .../modals/passphrase/Passphrase/index.js | 8 +-- .../modals/passphrase/Type/index.js | 2 +- .../Wallet/components/LeftNavigation/index.js | 4 +- 5 files changed, 92 insertions(+), 12 deletions(-) create mode 100644 src/components/images/WalletType/index.js diff --git a/src/components/images/WalletType/index.js b/src/components/images/WalletType/index.js new file mode 100644 index 00000000..49f095e0 --- /dev/null +++ b/src/components/images/WalletType/index.js @@ -0,0 +1,51 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import colors from 'config/colors'; +import styled from 'styled-components'; + +const SvgWrapper = styled.svg` + :hover { + path { + fill: ${props => props.hoverColor} + } + } +`; + +const Path = styled.path` + fill: ${props => props.color}; +`; + +export const HIDDEN = 'M23.9,13.6l-4-11C19.8,2.3,19.4,2,19,2h-3c-0.6,0-1,0.4-1,1s0.4,1,1,1h2.3l3.3,9H14h-4H2.4l3.3-9H8 c0.6,0,1-0.4,1-1S8.6,2,8,2H5C4.6,2,4.2,2.3,4.1,2.7l-4,11C0,13.7,0,13.9,0,14c0,0,0,0,0,0v0c0,0,0,0,0,0v5c0,1.7,1.3,3,3,3h5 c1.7,0,3-1.3,3-3v-4h2v4c0,1.7,1.3,3,3,3h5c1.7,0,3-1.3,3-3v-5c0,0,0,0,0,0v0c0,0,0,0,0,0C24,13.9,24,13.7,23.9,13.6z'; +export const STANDARD = 'M23,4H4H3C2.449,4,2,3.551,2,3s0.449-1,1-1h15v1h2V1c0-0.552-0.448-1-1-1H3C1.343,0,0,1.343,0,3v17 c0,2.209,1.791,4,4,4h19c0.552,0,1-0.448,1-1V5C24,4.448,23.552,4,23,4z M18,16c-1.105,0-2-0.895-2-2c0-1.105,0.895-2,2-2 s2,0.895,2,2C20,15.105,19.105,16,18,16z'; + +const Icon = ({ + type = 'standard', + size = 24, + color = colors.TEXT_SECONDARY, + hoverColor, + onClick, +}) => ( + + +); + +Icon.propTypes = { + type: PropTypes.string, + size: PropTypes.number, + color: PropTypes.string, + hoverColor: PropTypes.string, + onClick: PropTypes.func, +}; + +export default Icon; \ No newline at end of file diff --git a/src/components/modals/device/Type/index.js b/src/components/modals/device/Type/index.js index e9676ac3..8d0a4106 100644 --- a/src/components/modals/device/Type/index.js +++ b/src/components/modals/device/Type/index.js @@ -5,6 +5,11 @@ import styled from 'styled-components'; import { H3 } from 'components/Heading'; import P from 'components/Paragraph'; import Button from 'components/Button'; +import Icon from 'components/Icon'; +import Link from 'components/Link'; +import colors from 'config/colors'; +import icons from 'config/icons'; +import WalletTypeIcon from 'components/images/WalletType'; import type { Props } from 'components/modals/index'; @@ -13,6 +18,12 @@ const Wrapper = styled.div` padding: 24px 48px; `; +const StyledLink = styled(Link)` + position: absolute; + right: 15px; + top: 15px; +`; + const StyledButton = styled(Button)` margin: 0 0 10px 0; `; @@ -23,8 +34,7 @@ const Row = styled.div` padding: 10px 0; `; -class ForgetDevice extends Component { - +class WalletType extends Component { constructor(props: Props) { super(props); this.keyboardHandler = this.keyboardHandler.bind(this); @@ -56,17 +66,34 @@ class ForgetDevice extends Component { render() { if (!this.props.modal.opened) return null; const { device } = this.props.modal; - // const { onCancel } = this.props.modalActions; + const { onCancel } = this.props.modalActions; + return ( + { device.state && ( + + + + )}

RequestWalletType for { device.instanceLabel }?

- this.foo(false)}>Basic - this.foo(true)}>Hidden + + + Standard Wallet + +

Continue to access your standard wallet.

+ this.foo(false)}>Go to your standard wallet + + + + Hidden Wallet + +

You will be asked to enter your passphrase to unlock your hidden wallet.

+ this.foo(true)}>Go to your hidden wallet
); } } -export default ForgetDevice; \ No newline at end of file +export default WalletType; \ No newline at end of file diff --git a/src/components/modals/passphrase/Passphrase/index.js b/src/components/modals/passphrase/Passphrase/index.js index d95f138c..dec94bdf 100644 --- a/src/components/modals/passphrase/Passphrase/index.js +++ b/src/components/modals/passphrase/Passphrase/index.js @@ -212,7 +212,7 @@ class Passphrase extends Component { return (

Enter {this.state.deviceLabel} passphrase

-

Note that passphrase is case-sensitive.

+

Note that passphrase is case-sensitive. If you enter a wrong passphrase, you will not unlock the desired hidden wallet.

{ {!this.state.shouldShowSingleInput && ( - + {
-

If you want to access your default account

+ Changed your mind?   this.submitPassphrase(true)} - >Leave passphrase blank + >Go to your standard wallet

diff --git a/src/components/modals/passphrase/Type/index.js b/src/components/modals/passphrase/Type/index.js index 7ce9951c..c42cf3af 100644 --- a/src/components/modals/passphrase/Type/index.js +++ b/src/components/modals/passphrase/Type/index.js @@ -26,7 +26,7 @@ const Confirmation = (props: Props) => {

Complete the action on { device.label } device

-

TODO: add detailed text here. Explain passphrase/hidden wallet...

+

If you enter a wrong passphrase, you will not unlock the desired hidden wallet.

); diff --git a/src/views/Wallet/components/LeftNavigation/index.js b/src/views/Wallet/components/LeftNavigation/index.js index db79af1f..a19995db 100644 --- a/src/views/Wallet/components/LeftNavigation/index.js +++ b/src/views/Wallet/components/LeftNavigation/index.js @@ -4,6 +4,7 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import colors from 'config/colors'; import Icon from 'components/Icon'; +import WalletTypeIcon from 'components/images/WalletType'; import icons from 'config/icons'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import styled from 'styled-components'; @@ -197,11 +198,12 @@ class LeftNavigation extends React.PureComponent { this.handleOpen(); } }} - device={this.props.wallet.selectedDevice} + device={selectedDevice} disabled={!isDeviceAccessible && this.props.devices.length === 1} isOpen={this.props.wallet.dropdownOpened} icon={( + {this.props.devices.length > 1 && ( {this.props.devices.length} )} From c1a1e89ff3e4b786d89de6a147d60dc67491c4ed Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 8 Oct 2018 17:17:05 +0200 Subject: [PATCH 19/20] rename function --- src/components/modals/device/Type/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/modals/device/Type/index.js b/src/components/modals/device/Type/index.js index 8d0a4106..43114f61 100644 --- a/src/components/modals/device/Type/index.js +++ b/src/components/modals/device/Type/index.js @@ -51,13 +51,13 @@ class WalletType extends Component { keyboardHandler(event: KeyboardEvent): void { if (event.keyCode === 13) { event.preventDefault(); - this.foo(false); + this.changeType(false); } } keyboardHandler: (event: KeyboardEvent) => void; - foo(hidden: boolean) { + changeType(hidden: boolean) { const { modal } = this.props; if (!modal.opened) return; this.props.modalActions.onWalletTypeRequest(modal.device, hidden); @@ -82,14 +82,14 @@ class WalletType extends Component { Standard Wallet

Continue to access your standard wallet.

- this.foo(false)}>Go to your standard wallet + this.changeType(false)}>Go to your standard wallet Hidden Wallet

You will be asked to enter your passphrase to unlock your hidden wallet.

- this.foo(true)}>Go to your hidden wallet + this.changeType(true)}>Go to your hidden wallet
); From 5291ce32b16430e5475bdeccf393bedf9b0033f8 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 9 Oct 2018 10:12:10 +0200 Subject: [PATCH 20/20] add tooltip and texts to wallettype modal --- .../device/{Type => WalletType}/index.js | 50 +++++++++++++++++-- src/components/modals/index.js | 12 ++--- src/support/styles/Tooltip.js | 2 +- 3 files changed, 52 insertions(+), 12 deletions(-) rename src/components/modals/device/{Type => WalletType}/index.js (67%) diff --git a/src/components/modals/device/Type/index.js b/src/components/modals/device/WalletType/index.js similarity index 67% rename from src/components/modals/device/Type/index.js rename to src/components/modals/device/WalletType/index.js index 43114f61..260196c3 100644 --- a/src/components/modals/device/Type/index.js +++ b/src/components/modals/device/WalletType/index.js @@ -5,6 +5,7 @@ import styled from 'styled-components'; import { H3 } from 'components/Heading'; import P from 'components/Paragraph'; import Button from 'components/Button'; +import Tooltip from 'components/Tooltip'; import Icon from 'components/Icon'; import Link from 'components/Link'; import colors from 'config/colors'; @@ -28,12 +29,39 @@ const StyledButton = styled(Button)` margin: 0 0 10px 0; `; +const StyledTooltip = styled(Tooltip)` + position: absolute; + right: 0px; + top: 1px; +`; + +const StyledIcon = styled(Icon)` + position: relative; + top: -1px; + &:hover { + cursor: pointer; + } +`; + const Row = styled.div` display: flex; flex-direction: column; padding: 10px 0; `; +const Span = styled.div` + position: relative; + display: flex; + align-items: center; + flex-direction: row; + justify-content: center; +`; + +const Divider = styled.div` + margin: 20px 0; + border-top: 1px solid ${colors.DIVIDER}; +`; + class WalletType extends Component { constructor(props: Props) { super(props); @@ -77,17 +105,29 @@ class WalletType extends Component { )}

RequestWalletType for { device.instanceLabel }?

- + Standard Wallet - +

Continue to access your standard wallet.

this.changeType(false)}>Go to your standard wallet - - + + Hidden Wallet - + + + +

You will be asked to enter your passphrase to unlock your hidden wallet.

this.changeType(true)}>Go to your hidden wallet
diff --git a/src/components/modals/index.js b/src/components/modals/index.js index c78f7b3f..312613eb 100644 --- a/src/components/modals/index.js +++ b/src/components/modals/index.js @@ -1,5 +1,5 @@ /* @flow */ -import React, { Component } from 'react'; +import * as React from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; @@ -29,7 +29,7 @@ import ConfirmUnverifiedAddress from 'components/modals/confirm/UnverifiedAddres import ForgetDevice from 'components/modals/device/Forget'; import RememberDevice from 'components/modals/device/Remember'; import DuplicateDevice from 'components/modals/device/Duplicate'; -import RequestWalletType from 'components/modals/device/Type'; +import WalletType from 'components/modals/device/WalletType'; type OwnProps = { } @@ -52,13 +52,13 @@ type DispatchProps = { export type Props = StateProps & DispatchProps; -const Fade = ({ children, ...props }) => ( +const Fade = (props: { children: React.Node}) => ( - { children } + { props.children } ); @@ -85,7 +85,7 @@ const ModalWindow = styled.div` text-align: center; `; -class Modal extends Component { +class Modal extends React.Component { render() { if (!this.props.modal.opened) return null; @@ -125,7 +125,7 @@ class Modal extends Component { break; case CONNECT.REQUEST_WALLET_TYPE: - component = (); + component = (); break; default: diff --git a/src/support/styles/Tooltip.js b/src/support/styles/Tooltip.js index 10a7761b..34a602e8 100644 --- a/src/support/styles/Tooltip.js +++ b/src/support/styles/Tooltip.js @@ -4,7 +4,7 @@ import colors from 'config/colors'; const tooltipStyles = css` .rc-tooltip { position: absolute; - z-index: 1070; + z-index: 10070; visibility: visible; border: none; border-radius: 3px;