From 1b1fbb45f5053dc63b52bc4ed0735d515e0a1262 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 14 Jan 2019 02:46:41 +0100 Subject: [PATCH 01/16] add connecting flag to blockchain's state --- src/actions/BlockchainActions.js | 8 ++++++++ src/actions/constants/blockchain.js | 1 + src/reducers/BlockchainReducer.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index c3a5a0b1..f3e31755 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -19,6 +19,9 @@ export type BlockchainAction = { type: typeof BLOCKCHAIN.UPDATE_FEE, shortcut: string, feeLevels: Array, +} | { + type: typeof BLOCKCHAIN.START_SUBSCRIBE, + shortcut: string, } // Conditionally subscribe to blockchain backend @@ -52,6 +55,11 @@ export const subscribe = (networkName: string): PromiseAction => async (di const network = config.networks.find(c => c.shortcut === networkName); if (!network) return; + dispatch({ + type: BLOCKCHAIN.START_SUBSCRIBE, + shortcut: network.shortcut, + }); + switch (network.type) { case 'ethereum': await dispatch(EthereumBlockchainActions.subscribe(networkName)); diff --git a/src/actions/constants/blockchain.js b/src/actions/constants/blockchain.js index 9e19d3e3..7e1baeab 100644 --- a/src/actions/constants/blockchain.js +++ b/src/actions/constants/blockchain.js @@ -1,4 +1,5 @@ /* @flow */ +export const START_SUBSCRIBE: 'blockchain__start_subscribe' = 'blockchain__start_subscribe'; export const READY: 'blockchain__ready' = 'blockchain__ready'; export const UPDATE_FEE: 'blockchain__update_fee' = 'blockchain__update_fee'; \ No newline at end of file diff --git a/src/reducers/BlockchainReducer.js b/src/reducers/BlockchainReducer.js index 3831eb51..c5cc44ab 100644 --- a/src/reducers/BlockchainReducer.js +++ b/src/reducers/BlockchainReducer.js @@ -16,6 +16,7 @@ export type BlockchainNetwork = { feeTimestamp: number, feeLevels: Array, connected: boolean, + connecting: boolean, block: number, }; @@ -23,6 +24,26 @@ export type State = Array; export const initialState: State = []; +const onStartSubscribe = (state: State, shortcut: string): State => { + const network = state.find(b => b.shortcut === shortcut); + if (network) { + const others = state.filter(b => b !== network); + return others.concat([{ + ...network, + connecting: true, + }]); + } + + return state.concat([{ + shortcut, + connected: false, + connecting: true, + block: 0, + feeTimestamp: 0, + feeLevels: [], + }]); +}; + const onConnect = (state: State, action: BlockchainConnect): State => { const shortcut = action.payload.coin.shortcut.toLowerCase(); const network = state.find(b => b.shortcut === shortcut); @@ -31,13 +52,16 @@ const onConnect = (state: State, action: BlockchainConnect): State => { const others = state.filter(b => b !== network); return others.concat([{ ...network, + block: info.block, connected: true, + connecting: false, }]); } return state.concat([{ shortcut, connected: true, + connecting: false, block: info.block, feeTimestamp: 0, feeLevels: [], @@ -52,12 +76,14 @@ const onError = (state: State, action: BlockchainError): State => { return others.concat([{ ...network, connected: false, + connecting: false, }]); } return state.concat([{ shortcut, connected: false, + connecting: false, block: 0, feeTimestamp: 0, feeLevels: [], @@ -93,6 +119,8 @@ const updateFee = (state: State, shortcut: string, feeLevels: Array { switch (action.type) { + case BLOCKCHAIN_ACTION.START_SUBSCRIBE: + return onStartSubscribe(state, action.shortcut); case BLOCKCHAIN_EVENT.CONNECT: return onConnect(state, action); case BLOCKCHAIN_EVENT.ERROR: From 472d1cd453daf9883266a0d12e28b45785d6e963 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 14 Jan 2019 02:48:06 +0100 Subject: [PATCH 02/16] add loading state to a connect button when connecting to backend --- .../notifications/Context/components/Account/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/notifications/Context/components/Account/index.js b/src/components/notifications/Context/components/Account/index.js index a4924900..59d87299 100644 --- a/src/components/notifications/Context/components/Account/index.js +++ b/src/components/notifications/Context/components/Account/index.js @@ -8,6 +8,7 @@ import type { Props } from '../../index'; export default (props: Props) => { const { network, notification } = props.selectedAccount; if (!network || !notification) return null; + const blockchain = props.blockchain.find(b => b.shortcut === network.shortcut); if (notification.type === 'backend') { // special case: backend is down @@ -17,6 +18,7 @@ export default (props: Props) => { type="error" title={notification.title} message={notification.message} + isActionInProgress={blockchain && blockchain.connecting} actions={ [{ label: 'Connect', From 224337c4979de4a57c0d2fde49b1750e2a39bfb5 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 14 Jan 2019 12:08:21 +0100 Subject: [PATCH 03/16] disable add account button when device is not connected --- .../components/AccountMenu/index.js | 52 ++++++++----------- 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js b/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js index 202632b5..a89f980a 100644 --- a/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js @@ -71,24 +71,6 @@ const AddAccountIconWrapper = styled.div` margin-right: 12px; `; -const DiscoveryStatusWrapper = styled.div` - display: flex; - flex-direction: column; - width: 100%; - font-size: ${FONT_SIZE.BASE}; - padding: ${LEFT_NAVIGATION_ROW.PADDING}; - white-space: nowrap; - border-top: 1px solid ${colors.DIVIDER}; -`; - -const DiscoveryStatusText = styled.div` - display: block; - font-size: ${FONT_SIZE.SMALL}; - color: ${colors.TEXT_SECONDARY}; - overflow: hidden; - text-overflow: ellipsis; -`; - const DiscoveryLoadingWrapper = styled.div` display: flex; align-items: center; @@ -162,7 +144,28 @@ const AccountMenu = (props: Props) => { if (discovery && discovery.completed) { const lastAccount = deviceAccounts[deviceAccounts.length - 1]; - if (lastAccount && !lastAccount.empty) { + if (!selected.connected) { + discoveryStatus = ( + + + + + + + Add account + + + + ); + } else if (lastAccount && !lastAccount.empty) { discoveryStatus = ( @@ -199,17 +202,6 @@ const AccountMenu = (props: Props) => { ); } - } else if (!selected.connected) { - discoveryStatus = ( - - - Accounts could not be loaded - - {`Connect ${selected.instanceLabel} device`} - - - - ); } else { discoveryStatus = ( From ea804969cd21ca90c4ecbfb716df1b9f703255b7 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 14 Jan 2019 13:11:26 +0100 Subject: [PATCH 04/16] fix notification layout --- src/components/Notification/index.js | 94 +++++++++++++++------------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/src/components/Notification/index.js b/src/components/Notification/index.js index 6eade847..a8622de7 100644 --- a/src/components/Notification/index.js +++ b/src/components/Notification/index.js @@ -27,14 +27,20 @@ type Props = { const Wrapper = styled.div` width: 100%; position: relative; - padding: 24px 48px 9px 24px; + display: flex; + justify-content: center; + color: ${props => getPrimaryColor(props.type)}; + background: ${props => getSecondaryColor(props.type)}; +`; + +const Content = styled.div` + width: 100%; + max-width: 1170px; + padding: 24px; display: flex; flex-direction: row; text-align: left; - justify-content: center; align-items: center; - color: ${props => getPrimaryColor(props.type)}; - background: ${props => getSecondaryColor(props.type)}; `; const Body = styled.div` @@ -42,7 +48,6 @@ const Body = styled.div` `; const Message = styled.div` - padding-bottom: 13px; font-size: ${FONT_SIZE.SMALL}; `; @@ -56,7 +61,9 @@ const CloseClick = styled.div` position: absolute; right: 0; top: 0; - padding: 20px 10px 0 0; + padding-right: inherit; + padding-top: inherit; + cursor: pointer; `; const StyledIcon = styled(Icon)` @@ -86,7 +93,6 @@ const ActionContent = styled.div` display: flex; justify-content: right; align-items: flex-end; - padding-bottom: 14px; `; const Notification = (props: Props): React$Element => { @@ -94,43 +100,45 @@ const Notification = (props: Props): React$Element => { return ( - {props.loading && } - {props.cancelable && ( - close()}> - - - )} - - - - - - { props.title } - { props.message ? {props.message} : '' } - - - - {props.actions && props.actions.length > 0 && ( - - {props.actions.map(action => ( - { close(); action.callback(); }} - >{action.label} - - ))} - + + {props.loading && } + {props.cancelable && ( + close()}> + + )} - + + + + + + { props.title } + { props.message ? {props.message} : '' } + + + + {props.actions && props.actions.length > 0 && ( + + {props.actions.map(action => ( + { close(); action.callback(); }} + >{action.label} + + ))} + + )} + + ); }; From c77cd10f03fd928816377d5922817df03b964722 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Tue, 15 Jan 2019 13:54:34 +0100 Subject: [PATCH 05/16] send form clear button for ripple and eth --- src/actions/SendFormActions.js | 2 + src/actions/constants/send.js | 1 + src/actions/ethereum/SendFormActions.js | 19 ++++++ src/actions/ripple/SendFormActions.js | 20 ++++++ .../views/Account/Send/ethereum/index.js | 65 ++++++++++++++----- .../Wallet/views/Account/Send/ripple/index.js | 65 ++++++++++++++----- 6 files changed, 140 insertions(+), 32 deletions(-) diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index 16c6230a..84d8fcf8 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -29,6 +29,8 @@ export type SendFormAction = { type: typeof SEND.TOGGLE_ADVANCED | typeof SEND.TX_SENDING | typeof SEND.TX_ERROR, } | { type: typeof SEND.TX_COMPLETE, +} | { + type: typeof SEND.CLEAR, }; diff --git a/src/actions/constants/send.js b/src/actions/constants/send.js index a5d12906..577bdac2 100644 --- a/src/actions/constants/send.js +++ b/src/actions/constants/send.js @@ -7,3 +7,4 @@ export const TX_SENDING: 'send__tx_sending' = 'send__tx_sending'; export const TX_COMPLETE: 'send__tx_complete' = 'send__tx_complete'; export const TX_ERROR: 'send__tx_error' = 'send__tx_error'; export const TOGGLE_ADVANCED: 'send__toggle_advanced' = 'send__toggle_advanced'; +export const CLEAR: 'send__clear' = 'send__clear'; \ No newline at end of file diff --git a/src/actions/ethereum/SendFormActions.js b/src/actions/ethereum/SendFormActions.js index 82f4a25d..c2fde3bd 100644 --- a/src/actions/ethereum/SendFormActions.js +++ b/src/actions/ethereum/SendFormActions.js @@ -53,6 +53,13 @@ export const observe = (prevState: ReducersState, action: Action): ThunkAction = return; } + // clear transaction draft from session storage and reinitialize send form + if (action.type === SEND.CLEAR) { + dispatch(SessionStorageActions.clear()); + dispatch(init()); + return; + } + // if send form was not initialized if (currentState.sendFormEthereum.currency === '') { dispatch(init()); @@ -109,6 +116,8 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS network, } = getState().selectedAccount; + const { advanced } = getState().sendFormEthereum; + if (!account || !network) return; const stateFromStorage = dispatch(SessionStorageActions.loadEthereumDraftTransaction()); @@ -140,6 +149,7 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS recommendedGasPrice: gasPrice.toString(), gasLimit, gasPrice: gasPrice.toString(), + advanced, }, }); }; @@ -152,6 +162,14 @@ export const toggleAdvanced = (): Action => ({ networkType: 'ethereum', }); +/* +* Called from UI from "clear" button +*/ +export const onClear = (): Action => ({ + type: SEND.CLEAR, + networkType: 'ethereum', +}); + /* * Called from UI on "address" field change */ @@ -613,4 +631,5 @@ export default { onNonceChange, onDataChange, onSend, + onClear, }; \ No newline at end of file diff --git a/src/actions/ripple/SendFormActions.js b/src/actions/ripple/SendFormActions.js index ebe3fdc2..f763882e 100644 --- a/src/actions/ripple/SendFormActions.js +++ b/src/actions/ripple/SendFormActions.js @@ -35,6 +35,13 @@ export const observe = (prevState: ReducersState, action: Action): ThunkAction = return; } + // clear transaction draft from session storage and reinitialize send form + if (action.type === SEND.CLEAR) { + dispatch(SessionStorageActions.clear()); + dispatch(init()); + return; + } + // if send form was not initialized if (currentState.sendFormRipple.networkSymbol === '') { dispatch(init()); @@ -80,6 +87,8 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS network, } = getState().selectedAccount; + const { advanced } = getState().sendFormEthereum; + if (!account || account.networkType !== 'ripple' || !network) return; const stateFromStorage = dispatch(SessionStorageActions.loadRippleDraftTransaction()); @@ -107,6 +116,7 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS selectedFeeLevel, fee: network.fee.defaultFee, sequence: '1', + advanced, }, }); }; @@ -119,6 +129,15 @@ export const toggleAdvanced = (): Action => ({ networkType: 'ripple', }); +/* +* Called from UI from "clear" button +*/ +export const onClear = (): Action => ({ + type: SEND.CLEAR, + networkType: 'ripple', +}); + + /* * Called from UI on "address" field change */ @@ -368,4 +387,5 @@ export default { onFeeChange, onDestinationTagChange, onSend, + onClear, }; \ No newline at end of file diff --git a/src/views/Wallet/views/Account/Send/ethereum/index.js b/src/views/Wallet/views/Account/Send/ethereum/index.js index 4da01e1d..5a6df22f 100644 --- a/src/views/Wallet/views/Account/Send/ethereum/index.js +++ b/src/views/Wallet/views/Account/Send/ethereum/index.js @@ -142,17 +142,33 @@ const ToggleAdvancedSettingsButton = styled(Button)` min-height: 40px; padding: 0; display: flex; + flex: 1 1 0; align-items: center; font-weight: ${FONT_WEIGHT.SEMIBOLD}; `; -const SendButton = styled(Button)` - min-width: ${props => (props.isAdvancedSettingsHidden ? '50%' : '100%')}; - word-break: break-all; +const FormButtons = styled.div` + display: flex; + flex: 1 1; + @media screen and (max-width: ${SmallScreenWidth}) { margin-top: ${props => (props.isAdvancedSettingsHidden ? '10px' : 0)}; } + + Button + Button { + margin-left: 5px; + } +`; + +const SendButton = styled(Button)` + word-break: break-all; + flex: 1; + +`; + +const ClearButton = styled(Button)` + `; const AdvancedSettingsIcon = styled(Icon)` @@ -228,6 +244,7 @@ const AccountSend = (props: Props) => { onFeeLevelChange, updateFeeLevels, onSend, + onClear, } = props.sendFormActions; if (!device || !account || !discovery || !network || !shouldRender) { @@ -387,24 +404,40 @@ const AccountSend = (props: Props) => { {isAdvancedSettingsHidden && ( - onSend()} - > - {sendButtonText} - + + onClear()} + > + Clear + + onSend()} + > + {sendButtonText} + + )} {advanced && ( - onSend()} - > - {sendButtonText} - + + onClear()} + > + Clear + + onSend()} + > + {sendButtonText} + + )} diff --git a/src/views/Wallet/views/Account/Send/ripple/index.js b/src/views/Wallet/views/Account/Send/ripple/index.js index e9bc5e06..7ed90ced 100644 --- a/src/views/Wallet/views/Account/Send/ripple/index.js +++ b/src/views/Wallet/views/Account/Send/ripple/index.js @@ -129,17 +129,33 @@ const ToggleAdvancedSettingsButton = styled(Button)` min-height: 40px; padding: 0; display: flex; + flex: 1 1 0; align-items: center; font-weight: ${FONT_WEIGHT.SEMIBOLD}; `; -const SendButton = styled(Button)` - min-width: ${props => (props.isAdvancedSettingsHidden ? '50%' : '100%')}; - word-break: break-all; +const FormButtons = styled.div` + display: flex; + flex: 1 1; + @media screen and (max-width: ${SmallScreenWidth}) { margin-top: ${props => (props.isAdvancedSettingsHidden ? '10px' : 0)}; } + + Button + Button { + margin-left: 5px; + } +`; + +const SendButton = styled(Button)` + word-break: break-all; + flex: 1; + +`; + +const ClearButton = styled(Button)` + `; const AdvancedSettingsIcon = styled(Icon)` @@ -204,6 +220,7 @@ const AccountSend = (props: Props) => { onFeeLevelChange, updateFeeLevels, onSend, + onClear, } = props.sendFormActions; if (!device || !account || !discovery || !network || !shouldRender) { @@ -341,24 +358,40 @@ const AccountSend = (props: Props) => { {isAdvancedSettingsHidden && ( - onSend()} - > - {sendButtonText} - + + onClear()} + > + Clear + + onSend()} + > + {sendButtonText} + + )} {advanced && ( - onSend()} - > - {sendButtonText} - + + onClear()} + > + Clear + + onSend()} + > + {sendButtonText} + + )} From a8d39d95c2256cb7aa3c35e42e39fa4ba278b0cf Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Tue, 15 Jan 2019 15:24:41 +0100 Subject: [PATCH 06/16] separate clear from init function --- src/actions/SendFormActions.js | 6 ++-- src/actions/ethereum/SendFormActions.js | 45 +++++++++++++++++-------- src/actions/ripple/SendFormActions.js | 41 ++++++++++++++-------- src/reducers/SendFormEthereumReducer.js | 1 + src/reducers/SendFormRippleReducer.js | 1 + 5 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index 84d8fcf8..6116c403 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -18,19 +18,17 @@ import * as EthereumSendFormActions from './ethereum/SendFormActions'; import * as RippleSendFormActions from './ripple/SendFormActions'; export type SendFormAction = { - type: typeof SEND.INIT | typeof SEND.VALIDATION | typeof SEND.CHANGE, + type: typeof SEND.INIT | typeof SEND.VALIDATION | typeof SEND.CHANGE | typeof SEND.CLEAR, networkType: 'ethereum', state: EthereumState, } | { - type: typeof SEND.INIT | typeof SEND.VALIDATION | typeof SEND.CHANGE, + type: typeof SEND.INIT | typeof SEND.VALIDATION | typeof SEND.CHANGE | typeof SEND.CLEAR, networkType: 'ripple', state: RippleState, } | { type: typeof SEND.TOGGLE_ADVANCED | typeof SEND.TX_SENDING | typeof SEND.TX_ERROR, } | { type: typeof SEND.TX_COMPLETE, -} | { - type: typeof SEND.CLEAR, }; diff --git a/src/actions/ethereum/SendFormActions.js b/src/actions/ethereum/SendFormActions.js index c2fde3bd..52894fd0 100644 --- a/src/actions/ethereum/SendFormActions.js +++ b/src/actions/ethereum/SendFormActions.js @@ -53,13 +53,6 @@ export const observe = (prevState: ReducersState, action: Action): ThunkAction = return; } - // clear transaction draft from session storage and reinitialize send form - if (action.type === SEND.CLEAR) { - dispatch(SessionStorageActions.clear()); - dispatch(init()); - return; - } - // if send form was not initialized if (currentState.sendFormEthereum.currency === '') { dispatch(init()); @@ -116,8 +109,6 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS network, } = getState().selectedAccount; - const { advanced } = getState().sendFormEthereum; - if (!account || !network) return; const stateFromStorage = dispatch(SessionStorageActions.loadEthereumDraftTransaction()); @@ -149,7 +140,6 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS recommendedGasPrice: gasPrice.toString(), gasLimit, gasPrice: gasPrice.toString(), - advanced, }, }); }; @@ -165,10 +155,37 @@ export const toggleAdvanced = (): Action => ({ /* * Called from UI from "clear" button */ -export const onClear = (): Action => ({ - type: SEND.CLEAR, - networkType: 'ethereum', -}); +export const onClear = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const { network } = getState().selectedAccount; + const { advanced } = getState().sendFormEthereum; + + if (!network) return; + + // clear transaction draft from session storage + dispatch(SessionStorageActions.clear()); + + const gasPrice: BigNumber = await dispatch(BlockchainActions.getGasPrice(network.shortcut, network.defaultGasPrice)); + const gasLimit = network.defaultGasLimit.toString(); + const feeLevels = ValidationActions.getFeeLevels(network.symbol, gasPrice, gasLimit); + const selectedFeeLevel = ValidationActions.getSelectedFeeLevel(feeLevels, initialState.selectedFeeLevel); + + dispatch({ + type: SEND.CLEAR, + networkType: 'ethereum', + state: { + ...initialState, + networkName: network.shortcut, + networkSymbol: network.symbol, + currency: network.symbol, + feeLevels, + selectedFeeLevel, + recommendedGasPrice: gasPrice.toString(), + gasLimit, + gasPrice: gasPrice.toString(), + advanced, + }, + }); +}; /* * Called from UI on "address" field change diff --git a/src/actions/ripple/SendFormActions.js b/src/actions/ripple/SendFormActions.js index f763882e..90e78eec 100644 --- a/src/actions/ripple/SendFormActions.js +++ b/src/actions/ripple/SendFormActions.js @@ -35,13 +35,6 @@ export const observe = (prevState: ReducersState, action: Action): ThunkAction = return; } - // clear transaction draft from session storage and reinitialize send form - if (action.type === SEND.CLEAR) { - dispatch(SessionStorageActions.clear()); - dispatch(init()); - return; - } - // if send form was not initialized if (currentState.sendFormRipple.networkSymbol === '') { dispatch(init()); @@ -87,8 +80,6 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS network, } = getState().selectedAccount; - const { advanced } = getState().sendFormEthereum; - if (!account || account.networkType !== 'ripple' || !network) return; const stateFromStorage = dispatch(SessionStorageActions.loadRippleDraftTransaction()); @@ -116,7 +107,6 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS selectedFeeLevel, fee: network.fee.defaultFee, sequence: '1', - advanced, }, }); }; @@ -132,11 +122,34 @@ export const toggleAdvanced = (): Action => ({ /* * Called from UI from "clear" button */ -export const onClear = (): Action => ({ - type: SEND.CLEAR, - networkType: 'ripple', -}); +export const onClear = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const { network } = getState().selectedAccount; + const { advanced } = getState().sendFormRipple; + if (!network) return; + + // clear transaction draft from session storage + dispatch(SessionStorageActions.clear()); + + const blockchainFeeLevels = dispatch(BlockchainActions.getFeeLevels(network)); + const feeLevels = dispatch(ValidationActions.getFeeLevels(blockchainFeeLevels)); + const selectedFeeLevel = ValidationActions.getSelectedFeeLevel(feeLevels, initialState.selectedFeeLevel); + + dispatch({ + type: SEND.CLEAR, + networkType: 'ripple', + state: { + ...initialState, + networkName: network.shortcut, + networkSymbol: network.symbol, + feeLevels, + selectedFeeLevel, + fee: network.fee.defaultFee, + sequence: '1', + advanced, + }, + }); +}; /* * Called from UI on "address" field change diff --git a/src/reducers/SendFormEthereumReducer.js b/src/reducers/SendFormEthereumReducer.js index 5053f673..58b8e11d 100644 --- a/src/reducers/SendFormEthereumReducer.js +++ b/src/reducers/SendFormEthereumReducer.js @@ -82,6 +82,7 @@ export default (state: State = initialState, action: Action): State => { case SEND.INIT: case SEND.CHANGE: case SEND.VALIDATION: + case SEND.CLEAR: return action.state; case SEND.TOGGLE_ADVANCED: diff --git a/src/reducers/SendFormRippleReducer.js b/src/reducers/SendFormRippleReducer.js index f56083bc..63a1a717 100644 --- a/src/reducers/SendFormRippleReducer.js +++ b/src/reducers/SendFormRippleReducer.js @@ -75,6 +75,7 @@ export default (state: State = initialState, action: Action): State => { case SEND.INIT: case SEND.CHANGE: case SEND.VALIDATION: + case SEND.CLEAR: return action.state; case SEND.TOGGLE_ADVANCED: From 12d6113b9cc8345ca1d79ff64dfbb081efdc27a8 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Tue, 15 Jan 2019 15:35:31 +0100 Subject: [PATCH 07/16] fix paddings on small screens --- src/views/Wallet/views/Account/Send/ethereum/index.js | 9 ++++++--- src/views/Wallet/views/Account/Send/ripple/index.js | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/views/Wallet/views/Account/Send/ethereum/index.js b/src/views/Wallet/views/Account/Send/ethereum/index.js index 5a6df22f..7ce67e11 100644 --- a/src/views/Wallet/views/Account/Send/ethereum/index.js +++ b/src/views/Wallet/views/Account/Send/ethereum/index.js @@ -404,7 +404,9 @@ const AccountSend = (props: Props) => { {isAdvancedSettingsHidden && ( - + onClear()} @@ -413,7 +415,6 @@ const AccountSend = (props: Props) => { onSend()} > {sendButtonText} @@ -424,7 +425,9 @@ const AccountSend = (props: Props) => { {advanced && ( - + onClear()} diff --git a/src/views/Wallet/views/Account/Send/ripple/index.js b/src/views/Wallet/views/Account/Send/ripple/index.js index 7ed90ced..58650148 100644 --- a/src/views/Wallet/views/Account/Send/ripple/index.js +++ b/src/views/Wallet/views/Account/Send/ripple/index.js @@ -358,7 +358,9 @@ const AccountSend = (props: Props) => { {isAdvancedSettingsHidden && ( - + onClear()} @@ -367,7 +369,6 @@ const AccountSend = (props: Props) => { onSend()} > {sendButtonText} @@ -378,7 +379,9 @@ const AccountSend = (props: Props) => { {advanced && ( - + onClear()} From 449e97f377dcd4edaa7cb6abde318707693b60a4 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Fri, 18 Jan 2019 14:49:28 +0100 Subject: [PATCH 08/16] add new color for focused input border --- src/config/colors.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/colors.js b/src/config/colors.js index efca1cda..5d422fa6 100644 --- a/src/config/colors.js +++ b/src/config/colors.js @@ -34,4 +34,5 @@ export default { LABEL_COLOR: '#A9A9A9', TOOLTIP_BACKGROUND: '#333333', + INPUT_BORDER_FOCUSED: '#A9A9A9', }; \ No newline at end of file From 8edb6b66b8fada5ee6b013fbac351757a23798d6 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Fri, 18 Jan 2019 14:50:26 +0100 Subject: [PATCH 09/16] set border color when focused for input, button, textarea, select --- src/components/Button/index.js | 8 ++++++++ src/components/Select/index.js | 5 ++--- src/components/Textarea/index.js | 4 ++++ src/components/inputs/Input/index.js | 4 ++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/components/Button/index.js b/src/components/Button/index.js index c0704b56..2aef90ae 100644 --- a/src/components/Button/index.js +++ b/src/components/Button/index.js @@ -37,6 +37,10 @@ const Wrapper = styled.button` background: ${colors.GREEN_TERTIARY}; } + &:focus { + border-color: ${colors.INPUT_BORDER_FOCUSED}; + } + ${props => props.isDisabled && css` pointer-events: none; color: ${colors.TEXT_SECONDARY}; @@ -48,6 +52,10 @@ const Wrapper = styled.button` color: ${colors.TEXT_SECONDARY}; border: 1px solid ${colors.DIVIDER}; + &:focus { + border-color: ${colors.INPUT_BORDER_FOCUSED}; + } + &:hover { color: ${colors.TEXT_PRIMARY}; background: ${colors.DIVIDER}; diff --git a/src/components/Select/index.js b/src/components/Select/index.js index 1d7c020b..8c07de89 100644 --- a/src/components/Select/index.js +++ b/src/components/Select/index.js @@ -11,17 +11,16 @@ const styles = isSearchable => ({ width: '100%', color: colors.TEXT_SECONDARY, }), - control: (base, { isDisabled }) => ({ + control: (base, { isDisabled, isFocused }) => ({ ...base, minHeight: 'initial', height: '40px', borderRadius: '2px', - borderColor: colors.DIVIDER, + borderColor: isFocused ? colors.INPUT_BORDER_FOCUSED : colors.DIVIDER, boxShadow: 'none', background: isDisabled ? colors.LANDING : colors.WHITE, '&:hover': { cursor: isSearchable ? 'text' : 'pointer', - borderColor: colors.DIVIDER, }, }), indicatorSeparator: () => ({ diff --git a/src/components/Textarea/index.js b/src/components/Textarea/index.js index b0dbad2c..e0d4dbce 100644 --- a/src/components/Textarea/index.js +++ b/src/components/Textarea/index.js @@ -67,6 +67,10 @@ const StyledTextarea = styled(Textarea)` color: ${colors.TEXT_SECONDARY}; } + &:focus { + border-color: ${colors.INPUT_BORDER_FOCUSED}; + } + &:disabled { pointer-events: none; background: ${colors.GRAY_LIGHT}; diff --git a/src/components/inputs/Input/index.js b/src/components/inputs/Input/index.js index 5bda40dd..80635000 100644 --- a/src/components/inputs/Input/index.js +++ b/src/components/inputs/Input/index.js @@ -59,6 +59,10 @@ const StyledInput = styled.input` background-color: ${colors.WHITE}; transition: ${TRANSITION.HOVER}; + &:focus { + border-color: ${colors.INPUT_BORDER_FOCUSED}; + } + &:disabled { pointer-events: none; background: ${colors.GRAY_LIGHT}; From bdd43b49b24d3f48494d41f82e19b18f9c4e46a8 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Fri, 18 Jan 2019 15:55:20 +0100 Subject: [PATCH 10/16] add box shadow --- src/components/Button/index.js | 10 ++++++++-- src/components/Select/index.js | 4 ++-- src/components/Textarea/index.js | 3 ++- src/components/inputs/Input/index.js | 3 ++- src/config/colors.js | 4 +++- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/components/Button/index.js b/src/components/Button/index.js index 2aef90ae..a5f3931d 100644 --- a/src/components/Button/index.js +++ b/src/components/Button/index.js @@ -38,7 +38,8 @@ const Wrapper = styled.button` } &:focus { - border-color: ${colors.INPUT_BORDER_FOCUSED}; + border-color: ${colors.INPUT_FOCUSED_BORDER}; + box-shadow: 0 0px 6px 0 ${colors.INPUT_FOCUSED_SHADOW}; } ${props => props.isDisabled && css` @@ -53,7 +54,7 @@ const Wrapper = styled.button` border: 1px solid ${colors.DIVIDER}; &:focus { - border-color: ${colors.INPUT_BORDER_FOCUSED}; + border-color: ${colors.INPUT_FOCUSED_BORDER}; } &:hover { @@ -72,6 +73,11 @@ const Wrapper = styled.button` border: 0px; color: ${colors.TEXT_SECONDARY}; + &:focus { + color: ${colors.TEXT_PRIMARY}; + box-shadow: none; + } + &:hover, &:active { color: ${colors.TEXT_PRIMARY}; diff --git a/src/components/Select/index.js b/src/components/Select/index.js index 8c07de89..a3691964 100644 --- a/src/components/Select/index.js +++ b/src/components/Select/index.js @@ -16,8 +16,8 @@ const styles = isSearchable => ({ minHeight: 'initial', height: '40px', borderRadius: '2px', - borderColor: isFocused ? colors.INPUT_BORDER_FOCUSED : colors.DIVIDER, - boxShadow: 'none', + borderColor: isFocused ? colors.INPUT_FOCUSED_BORDER : colors.DIVIDER, + boxShadow: isFocused ? `0 0px 6px 0 ${colors.INPUT_FOCUSED_SHADOW}` : 'none', background: isDisabled ? colors.LANDING : colors.WHITE, '&:hover': { cursor: isSearchable ? 'text' : 'pointer', diff --git a/src/components/Textarea/index.js b/src/components/Textarea/index.js index e0d4dbce..b5064ee7 100644 --- a/src/components/Textarea/index.js +++ b/src/components/Textarea/index.js @@ -68,7 +68,8 @@ const StyledTextarea = styled(Textarea)` } &:focus { - border-color: ${colors.INPUT_BORDER_FOCUSED}; + border-color: ${colors.INPUT_FOCUSED_BORDER}; + box-shadow: 0 0px 6px 0 ${colors.INPUT_FOCUSED_SHADOW}; } &:disabled { diff --git a/src/components/inputs/Input/index.js b/src/components/inputs/Input/index.js index 80635000..ee2aa96a 100644 --- a/src/components/inputs/Input/index.js +++ b/src/components/inputs/Input/index.js @@ -60,7 +60,8 @@ const StyledInput = styled.input` transition: ${TRANSITION.HOVER}; &:focus { - border-color: ${colors.INPUT_BORDER_FOCUSED}; + border-color: ${colors.INPUT_FOCUSED_BORDER}; + box-shadow: 0 0px 6px 0 ${colors.INPUT_FOCUSED_SHADOW}; } &:disabled { diff --git a/src/config/colors.js b/src/config/colors.js index 5d422fa6..23140583 100644 --- a/src/config/colors.js +++ b/src/config/colors.js @@ -34,5 +34,7 @@ export default { LABEL_COLOR: '#A9A9A9', TOOLTIP_BACKGROUND: '#333333', - INPUT_BORDER_FOCUSED: '#A9A9A9', + + INPUT_FOCUSED_BORDER: '#A9A9A9', + INPUT_FOCUSED_SHADOW: '#d6d7d7', }; \ No newline at end of file From 97918224a2b31948b138e1499e01702d5f1a2c73 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Sun, 20 Jan 2019 19:08:36 +0100 Subject: [PATCH 11/16] fix device header ux --- .../DeviceMenu/components/MenuItems/index.js | 1 - .../components/DeviceMenu/index.js | 33 ++++++++++++++----- .../components/Divider/index.js | 4 ++- .../Wallet/components/LeftNavigation/index.js | 12 ++++--- 4 files changed, 35 insertions(+), 15 deletions(-) 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 53fc615b..9099248d 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 @@ -9,7 +9,6 @@ import { FONT_SIZE } from 'config/variables'; const Wrapper = styled.div` padding: 0px 24px 8px 19px; - border-bottom: 1px solid ${colors.DIVIDER}; background: ${colors.WHITE}; `; diff --git a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js index 9cdc96be..9c251a71 100644 --- a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js @@ -3,6 +3,10 @@ import React, { PureComponent } from 'react'; import styled from 'styled-components'; import TrezorConnect from 'trezor-connect'; import type { TrezorDevice } from 'flowtype'; + +import COLORS from 'config/colors'; +import { FONT_SIZE, FONT_WEIGHT } from 'config/variables'; + import Button from 'components/Button'; import * as deviceUtils from 'utils/device'; import MenuItems from './components/MenuItems'; @@ -10,11 +14,16 @@ import DeviceList from './components/DeviceList'; import type { Props } from '../common'; -import AsideDivider from '../Divider'; +import Divider from '../Divider'; + +const Wrapper = styled.div` + border-bottom: 1px solid #E3E3E3; + background: white; + box-shadow: 0 3px 8px rgba(0,0,0,0.06); +`; -const Wrapper = styled.div``; const ButtonWrapper = styled.div` - margin-top: 10px; + margin: 10px 0; padding: 0 10px; display: flex; `; @@ -22,6 +31,14 @@ const StyledButton = styled(Button)` flex: 1; `; +const StyledDivider = styled(Divider)` + background: #fff; + color: ${COLORS.TEXT_PRIMARY}; + font-weight: ${FONT_WEIGHT.MEDIUM}; + font-size: ${FONT_SIZE.BASE}; + border: none; +`; + type DeviceMenuItem = { type: string; label: string; @@ -104,18 +121,18 @@ class DeviceMenu extends PureComponent { return ( {this.showMenuItems() && } - {this.showDivider() && } + {this.showDivider() && } - - {deviceUtils.isWebUSB(transport) && ( + {deviceUtils.isWebUSB(transport) && ( + Check for devices - )} - + + )} ); } diff --git a/src/views/Wallet/components/LeftNavigation/components/Divider/index.js b/src/views/Wallet/components/LeftNavigation/components/Divider/index.js index 8f29337e..0a46446f 100644 --- a/src/views/Wallet/components/LeftNavigation/components/Divider/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/Divider/index.js @@ -19,10 +19,11 @@ const Wrapper = styled.div` `; const Divider = ({ - textLeft, textRight, hasBorder = false, + textLeft, textRight, hasBorder = false, className, }) => (

{textLeft}

{textRight}

@@ -30,6 +31,7 @@ const Divider = ({ ); Divider.propTypes = { + className: PropTypes.string, textLeft: PropTypes.string, textRight: PropTypes.string, hasBorder: PropTypes.bool, diff --git a/src/views/Wallet/components/LeftNavigation/index.js b/src/views/Wallet/components/LeftNavigation/index.js index cca5eab1..5b4801ce 100644 --- a/src/views/Wallet/components/LeftNavigation/index.js +++ b/src/views/Wallet/components/LeftNavigation/index.js @@ -132,14 +132,17 @@ class LeftNavigation extends React.PureComponent { const deviceReady = selectedDevice && selectedDevice.features && selectedDevice.mode === 'normal'; if (dropdownOpened) { this.setState({ shouldRenderDeviceSelection: true }); - } else if (hasNetwork) { + } else { + this.setState({ shouldRenderDeviceSelection: false }); + } + if (hasNetwork) { this.setState({ - shouldRenderDeviceSelection: false, + // shouldRenderDeviceSelection: false, animationType: 'slide-left', }); } else { this.setState({ - shouldRenderDeviceSelection: false, + // shouldRenderDeviceSelection: false, animationType: deviceReady ? 'slide-right' : null, }); } @@ -152,7 +155,6 @@ class LeftNavigation extends React.PureComponent { && location && location.state && location.state.network - && !this.state.shouldRenderDeviceSelection && this.state.animationType === 'slide-left'; } @@ -162,7 +164,7 @@ class LeftNavigation extends React.PureComponent { } shouldRenderCoins() { - return !this.state.shouldRenderDeviceSelection && this.state.animationType !== 'slide-left'; + return this.state.animationType !== 'slide-left'; } render() { From 6662c705bcb386450d00885b35ea22550cc03c4c Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 21 Jan 2019 14:43:56 +0100 Subject: [PATCH 12/16] hover for menu items --- .../components/DeviceMenu/components/MenuItems/index.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 9099248d..c39de5a8 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 @@ -8,17 +8,20 @@ import colors from 'config/colors'; import { FONT_SIZE } from 'config/variables'; const Wrapper = styled.div` - padding: 0px 24px 8px 19px; background: ${colors.WHITE}; `; const Item = styled.div` - padding: 4px 2px; + padding: 6px 24px; display: flex; align-items: center; font-size: ${FONT_SIZE.BASE}; cursor: pointer; - color: ${colors.TEXT_SECONDARY}; + color: ${colors.TEXT_SECONDARY}; + + &:hover { + background: ${colors.GRAY_LIGHT}; + } `; const Label = styled.div` From 59c4e69ab4430e4a747c246dc659176d0559f1db Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 21 Jan 2019 16:20:05 +0100 Subject: [PATCH 13/16] missing position absolute --- .../components/LeftNavigation/components/DeviceMenu/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js index 9c251a71..f49f1764 100644 --- a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js @@ -17,6 +17,7 @@ import type { Props } from '../common'; import Divider from '../Divider'; const Wrapper = styled.div` + position: absolute; border-bottom: 1px solid #E3E3E3; background: white; box-shadow: 0 3px 8px rgba(0,0,0,0.06); From 251eb61177dc3de9580f609ff5c3deb40b70b266 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 21 Jan 2019 16:51:52 +0100 Subject: [PATCH 14/16] add slide down animation for device menu --- src/components/DeviceHeader/index.js | 1 + src/config/animations.js | 9 +++++++++ .../LeftNavigation/components/DeviceMenu/index.js | 2 ++ 3 files changed, 12 insertions(+) diff --git a/src/components/DeviceHeader/index.js b/src/components/DeviceHeader/index.js index cdce9e46..0742e4e3 100644 --- a/src/components/DeviceHeader/index.js +++ b/src/components/DeviceHeader/index.js @@ -15,6 +15,7 @@ const Wrapper = styled.div` position: relative; height: 70px; width: 320px; + z-index: 10; display: flex; align-items: center; background: ${props => (props.disabled ? colors.GRAY_LIGHT : 'transparent')}; diff --git a/src/config/animations.js b/src/config/animations.js index 950ea9e2..c7fee813 100644 --- a/src/config/animations.js +++ b/src/config/animations.js @@ -71,4 +71,13 @@ export const FADE_IN = keyframes` 100% { opacity: 1; } +`; + +export const SLIDE_DOWN = keyframes` + 0% { + transform: translateY(-100%); + } + 100% { + transform: translateY(0%); + } `; \ No newline at end of file diff --git a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js index f49f1764..5879fc79 100644 --- a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js @@ -6,6 +6,7 @@ import type { TrezorDevice } from 'flowtype'; import COLORS from 'config/colors'; import { FONT_SIZE, FONT_WEIGHT } from 'config/variables'; +import { SLIDE_DOWN } from 'config/animations'; import Button from 'components/Button'; import * as deviceUtils from 'utils/device'; @@ -21,6 +22,7 @@ const Wrapper = styled.div` border-bottom: 1px solid #E3E3E3; background: white; box-shadow: 0 3px 8px rgba(0,0,0,0.06); + animation: ${SLIDE_DOWN} 0.25s cubic-bezier(0.17, 0.04, 0.03, 0.94) forwards; `; const ButtonWrapper = styled.div` From 9f190dc993a85b58605d96ad60670da843720b7f Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Mon, 21 Jan 2019 17:12:17 +0100 Subject: [PATCH 15/16] strech device menu width to its parent's width --- .../components/LeftNavigation/components/DeviceMenu/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js index 5879fc79..cb4f36d9 100644 --- a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js @@ -19,6 +19,8 @@ import Divider from '../Divider'; const Wrapper = styled.div` position: absolute; + width: 100%; + padding-bottom: 8px; border-bottom: 1px solid #E3E3E3; background: white; box-shadow: 0 3px 8px rgba(0,0,0,0.06); From cc41a963cd8df85e7d62e074b4abbb4c4bcbd769 Mon Sep 17 00:00:00 2001 From: slowbackspace Date: Tue, 22 Jan 2019 12:57:10 +0100 Subject: [PATCH 16/16] set minHeight to fix rendering of devicemenu for unitialized device --- .../components/DeviceMenu/index.js | 9 ++++- .../Wallet/components/LeftNavigation/index.js | 40 +++++++++++++------ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js index cb4f36d9..4797b422 100644 --- a/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/DeviceMenu/index.js @@ -54,6 +54,7 @@ class DeviceMenu extends PureComponent { super(props); this.mouseDownHandler = this.mouseDownHandler.bind(this); this.blurHandler = this.blurHandler.bind(this); + this.myRef = React.createRef(); } componentDidMount(): void { @@ -85,6 +86,10 @@ class DeviceMenu extends PureComponent { } } + getMenuHeight(): number { + return this.myRef.current ? this.myRef.current.getBoundingClientRect().height : 0; + } + blurHandler(): void { this.props.toggleDeviceDropdown(false); } @@ -118,13 +123,15 @@ class DeviceMenu extends PureComponent { return deviceUtils.isDeviceAccessible(this.props.wallet.selectedDevice); } + myRef: { current: ?HTMLDivElement } + render() { const { devices, onSelectDevice, forgetDevice } = this.props; const { transport } = this.props.connect; const { selectedDevice } = this.props.wallet; return ( - + {this.showMenuItems() && } {this.showDivider() && } ({ const Body = styled.div` width: 320px; + min-height: ${props => (props.minHeight ? `${props.minHeight}px` : '0px')}; `; const Help = styled.div` @@ -109,45 +110,48 @@ const TransitionMenu = (props: TransitionMenuProps): React$Element { constructor(props: Props) { super(props); + this.deviceMenuRef = React.createRef(); const { location } = this.props.router; const hasNetwork = location && location.state && location.state.network; this.state = { animationType: hasNetwork ? 'slide-left' : null, - shouldRenderDeviceSelection: false, clicked: false, + bodyMinHeight: 0, }; } + componentDidMount() { + this.recalculateBodyMinHeight(); + } + componentWillReceiveProps(nextProps: Props) { - const { dropdownOpened, selectedDevice } = nextProps.wallet; + const { selectedDevice } = nextProps.wallet; const { location } = nextProps.router; const hasNetwork = location && location.state.network; const deviceReady = selectedDevice && selectedDevice.features && selectedDevice.mode === 'normal'; - if (dropdownOpened) { - this.setState({ shouldRenderDeviceSelection: true }); - } else { - this.setState({ shouldRenderDeviceSelection: false }); - } + if (hasNetwork) { this.setState({ - // shouldRenderDeviceSelection: false, animationType: 'slide-left', }); } else { this.setState({ - // shouldRenderDeviceSelection: false, animationType: deviceReady ? 'slide-right' : null, }); } } + componentDidUpdate() { + this.recalculateBodyMinHeight(); + } + shouldRenderAccounts() { const { selectedDevice } = this.props.wallet; const { location } = this.props.router; @@ -167,6 +171,16 @@ class LeftNavigation extends React.PureComponent { return this.state.animationType !== 'slide-left'; } + recalculateBodyMinHeight() { + if (this.deviceMenuRef.current) { + this.setState({ + bodyMinHeight: this.deviceMenuRef.current.getMenuHeight(), + }); + } + } + + deviceMenuRef: { current: any }; + render() { const { props } = this; let menu; @@ -184,7 +198,7 @@ class LeftNavigation extends React.PureComponent { ); } - const { selectedDevice } = props.wallet; + const { selectedDevice, dropdownOpened } = props.wallet; const isDeviceAccessible = deviceUtils.isDeviceAccessible(selectedDevice); return ( { )} {...this.props} /> - - {this.state.shouldRenderDeviceSelection && } + + {dropdownOpened && } {isDeviceAccessible && menu}