mirror of
https://github.com/trezor/trezor-wallet
synced 2025-01-09 15:40:55 +00:00
merge master
This commit is contained in:
commit
2be71ddea2
@ -19,6 +19,9 @@ export type BlockchainAction = {
|
|||||||
type: typeof BLOCKCHAIN.UPDATE_FEE,
|
type: typeof BLOCKCHAIN.UPDATE_FEE,
|
||||||
shortcut: string,
|
shortcut: string,
|
||||||
feeLevels: Array<BlockchainFeeLevel>,
|
feeLevels: Array<BlockchainFeeLevel>,
|
||||||
|
} | {
|
||||||
|
type: typeof BLOCKCHAIN.START_SUBSCRIBE,
|
||||||
|
shortcut: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conditionally subscribe to blockchain backend
|
// Conditionally subscribe to blockchain backend
|
||||||
@ -52,6 +55,11 @@ export const subscribe = (networkName: string): PromiseAction<void> => async (di
|
|||||||
const network = config.networks.find(c => c.shortcut === networkName);
|
const network = config.networks.find(c => c.shortcut === networkName);
|
||||||
if (!network) return;
|
if (!network) return;
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: BLOCKCHAIN.START_SUBSCRIBE,
|
||||||
|
shortcut: network.shortcut,
|
||||||
|
});
|
||||||
|
|
||||||
switch (network.type) {
|
switch (network.type) {
|
||||||
case 'ethereum':
|
case 'ethereum':
|
||||||
await dispatch(EthereumBlockchainActions.subscribe(networkName));
|
await dispatch(EthereumBlockchainActions.subscribe(networkName));
|
||||||
|
@ -18,11 +18,11 @@ import * as EthereumSendFormActions from './ethereum/SendFormActions';
|
|||||||
import * as RippleSendFormActions from './ripple/SendFormActions';
|
import * as RippleSendFormActions from './ripple/SendFormActions';
|
||||||
|
|
||||||
export type SendFormAction = {
|
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',
|
networkType: 'ethereum',
|
||||||
state: EthereumState,
|
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',
|
networkType: 'ripple',
|
||||||
state: RippleState,
|
state: RippleState,
|
||||||
} | {
|
} | {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
|
export const START_SUBSCRIBE: 'blockchain__start_subscribe' = 'blockchain__start_subscribe';
|
||||||
export const READY: 'blockchain__ready' = 'blockchain__ready';
|
export const READY: 'blockchain__ready' = 'blockchain__ready';
|
||||||
export const UPDATE_FEE: 'blockchain__update_fee' = 'blockchain__update_fee';
|
export const UPDATE_FEE: 'blockchain__update_fee' = 'blockchain__update_fee';
|
@ -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_COMPLETE: 'send__tx_complete' = 'send__tx_complete';
|
||||||
export const TX_ERROR: 'send__tx_error' = 'send__tx_error';
|
export const TX_ERROR: 'send__tx_error' = 'send__tx_error';
|
||||||
export const TOGGLE_ADVANCED: 'send__toggle_advanced' = 'send__toggle_advanced';
|
export const TOGGLE_ADVANCED: 'send__toggle_advanced' = 'send__toggle_advanced';
|
||||||
|
export const CLEAR: 'send__clear' = 'send__clear';
|
@ -152,6 +152,41 @@ export const toggleAdvanced = (): Action => ({
|
|||||||
networkType: 'ethereum',
|
networkType: 'ethereum',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from UI from "clear" button
|
||||||
|
*/
|
||||||
|
export const onClear = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||||
|
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
|
* Called from UI on "address" field change
|
||||||
*/
|
*/
|
||||||
@ -613,4 +648,5 @@ export default {
|
|||||||
onNonceChange,
|
onNonceChange,
|
||||||
onDataChange,
|
onDataChange,
|
||||||
onSend,
|
onSend,
|
||||||
|
onClear,
|
||||||
};
|
};
|
@ -119,6 +119,38 @@ export const toggleAdvanced = (): Action => ({
|
|||||||
networkType: 'ripple',
|
networkType: 'ripple',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from UI from "clear" button
|
||||||
|
*/
|
||||||
|
export const onClear = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||||
|
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
|
* Called from UI on "address" field change
|
||||||
*/
|
*/
|
||||||
@ -368,4 +400,5 @@ export default {
|
|||||||
onFeeChange,
|
onFeeChange,
|
||||||
onDestinationTagChange,
|
onDestinationTagChange,
|
||||||
onSend,
|
onSend,
|
||||||
|
onClear,
|
||||||
};
|
};
|
@ -37,6 +37,11 @@ const Wrapper = styled.button`
|
|||||||
background: ${colors.GREEN_TERTIARY};
|
background: ${colors.GREEN_TERTIARY};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: ${colors.INPUT_FOCUSED_BORDER};
|
||||||
|
box-shadow: 0 0px 6px 0 ${colors.INPUT_FOCUSED_SHADOW};
|
||||||
|
}
|
||||||
|
|
||||||
${props => props.isDisabled && css`
|
${props => props.isDisabled && css`
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
color: ${colors.TEXT_SECONDARY};
|
color: ${colors.TEXT_SECONDARY};
|
||||||
@ -48,6 +53,10 @@ const Wrapper = styled.button`
|
|||||||
color: ${colors.TEXT_SECONDARY};
|
color: ${colors.TEXT_SECONDARY};
|
||||||
border: 1px solid ${colors.DIVIDER};
|
border: 1px solid ${colors.DIVIDER};
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: ${colors.INPUT_FOCUSED_BORDER};
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${colors.TEXT_PRIMARY};
|
color: ${colors.TEXT_PRIMARY};
|
||||||
background: ${colors.DIVIDER};
|
background: ${colors.DIVIDER};
|
||||||
@ -64,6 +73,11 @@ const Wrapper = styled.button`
|
|||||||
border: 0px;
|
border: 0px;
|
||||||
color: ${colors.TEXT_SECONDARY};
|
color: ${colors.TEXT_SECONDARY};
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
color: ${colors.TEXT_PRIMARY};
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:active {
|
&:active {
|
||||||
color: ${colors.TEXT_PRIMARY};
|
color: ${colors.TEXT_PRIMARY};
|
||||||
|
@ -15,6 +15,7 @@ const Wrapper = styled.div`
|
|||||||
position: relative;
|
position: relative;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
width: 320px;
|
width: 320px;
|
||||||
|
z-index: 10;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${props => (props.disabled ? colors.GRAY_LIGHT : 'transparent')};
|
background: ${props => (props.disabled ? colors.GRAY_LIGHT : 'transparent')};
|
||||||
|
@ -27,14 +27,20 @@ type Props = {
|
|||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
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;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: ${props => getPrimaryColor(props.type)};
|
|
||||||
background: ${props => getSecondaryColor(props.type)};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Body = styled.div`
|
const Body = styled.div`
|
||||||
@ -42,7 +48,6 @@ const Body = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Message = styled.div`
|
const Message = styled.div`
|
||||||
padding-bottom: 13px;
|
|
||||||
font-size: ${FONT_SIZE.SMALL};
|
font-size: ${FONT_SIZE.SMALL};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -56,7 +61,9 @@ const CloseClick = styled.div`
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 20px 10px 0 0;
|
padding-right: inherit;
|
||||||
|
padding-top: inherit;
|
||||||
|
cursor: pointer;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledIcon = styled(Icon)`
|
const StyledIcon = styled(Icon)`
|
||||||
@ -86,7 +93,6 @@ const ActionContent = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: right;
|
justify-content: right;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
padding-bottom: 14px;
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Notification = (props: Props): React$Element<string> => {
|
const Notification = (props: Props): React$Element<string> => {
|
||||||
@ -94,43 +100,45 @@ const Notification = (props: Props): React$Element<string> => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper className={props.className} type={props.type}>
|
<Wrapper className={props.className} type={props.type}>
|
||||||
{props.loading && <Loader size={50} /> }
|
<Content>
|
||||||
{props.cancelable && (
|
{props.loading && <Loader size={50} /> }
|
||||||
<CloseClick onClick={() => close()}>
|
{props.cancelable && (
|
||||||
<Icon
|
<CloseClick onClick={() => close()}>
|
||||||
color={getPrimaryColor(props.type)}
|
<Icon
|
||||||
icon={icons.CLOSE}
|
color={getPrimaryColor(props.type)}
|
||||||
size={20}
|
icon={icons.CLOSE}
|
||||||
/>
|
size={20}
|
||||||
</CloseClick>
|
/>
|
||||||
)}
|
</CloseClick>
|
||||||
<Body>
|
|
||||||
<IconWrapper>
|
|
||||||
<StyledIcon
|
|
||||||
color={getPrimaryColor(props.type)}
|
|
||||||
icon={getIcon(props.type)}
|
|
||||||
/>
|
|
||||||
</IconWrapper>
|
|
||||||
<Texts>
|
|
||||||
<Title>{ props.title }</Title>
|
|
||||||
{ props.message ? <Message>{props.message}</Message> : '' }
|
|
||||||
</Texts>
|
|
||||||
</Body>
|
|
||||||
<AdditionalContent>
|
|
||||||
{props.actions && props.actions.length > 0 && (
|
|
||||||
<ActionContent>
|
|
||||||
{props.actions.map(action => (
|
|
||||||
<NotificationButton
|
|
||||||
key={action.label}
|
|
||||||
type={props.type}
|
|
||||||
isLoading={props.isActionInProgress}
|
|
||||||
onClick={() => { close(); action.callback(); }}
|
|
||||||
>{action.label}
|
|
||||||
</NotificationButton>
|
|
||||||
))}
|
|
||||||
</ActionContent>
|
|
||||||
)}
|
)}
|
||||||
</AdditionalContent>
|
<Body>
|
||||||
|
<IconWrapper>
|
||||||
|
<StyledIcon
|
||||||
|
color={getPrimaryColor(props.type)}
|
||||||
|
icon={getIcon(props.type)}
|
||||||
|
/>
|
||||||
|
</IconWrapper>
|
||||||
|
<Texts>
|
||||||
|
<Title>{ props.title }</Title>
|
||||||
|
{ props.message ? <Message>{props.message}</Message> : '' }
|
||||||
|
</Texts>
|
||||||
|
</Body>
|
||||||
|
<AdditionalContent>
|
||||||
|
{props.actions && props.actions.length > 0 && (
|
||||||
|
<ActionContent>
|
||||||
|
{props.actions.map(action => (
|
||||||
|
<NotificationButton
|
||||||
|
key={action.label}
|
||||||
|
type={props.type}
|
||||||
|
isLoading={props.isActionInProgress}
|
||||||
|
onClick={() => { close(); action.callback(); }}
|
||||||
|
>{action.label}
|
||||||
|
</NotificationButton>
|
||||||
|
))}
|
||||||
|
</ActionContent>
|
||||||
|
)}
|
||||||
|
</AdditionalContent>
|
||||||
|
</Content>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -11,17 +11,16 @@ const styles = isSearchable => ({
|
|||||||
width: '100%',
|
width: '100%',
|
||||||
color: colors.TEXT_SECONDARY,
|
color: colors.TEXT_SECONDARY,
|
||||||
}),
|
}),
|
||||||
control: (base, { isDisabled }) => ({
|
control: (base, { isDisabled, isFocused }) => ({
|
||||||
...base,
|
...base,
|
||||||
minHeight: 'initial',
|
minHeight: 'initial',
|
||||||
height: '40px',
|
height: '40px',
|
||||||
borderRadius: '2px',
|
borderRadius: '2px',
|
||||||
borderColor: colors.DIVIDER,
|
borderColor: isFocused ? colors.INPUT_FOCUSED_BORDER : colors.DIVIDER,
|
||||||
boxShadow: 'none',
|
boxShadow: isFocused ? `0 0px 6px 0 ${colors.INPUT_FOCUSED_SHADOW}` : 'none',
|
||||||
background: isDisabled ? colors.LANDING : colors.WHITE,
|
background: isDisabled ? colors.LANDING : colors.WHITE,
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
cursor: isSearchable ? 'text' : 'pointer',
|
cursor: isSearchable ? 'text' : 'pointer',
|
||||||
borderColor: colors.DIVIDER,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
indicatorSeparator: () => ({
|
indicatorSeparator: () => ({
|
||||||
|
@ -67,6 +67,11 @@ const StyledTextarea = styled(Textarea)`
|
|||||||
color: ${colors.TEXT_SECONDARY};
|
color: ${colors.TEXT_SECONDARY};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: ${colors.INPUT_FOCUSED_BORDER};
|
||||||
|
box-shadow: 0 0px 6px 0 ${colors.INPUT_FOCUSED_SHADOW};
|
||||||
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background: ${colors.GRAY_LIGHT};
|
background: ${colors.GRAY_LIGHT};
|
||||||
|
@ -59,6 +59,11 @@ const StyledInput = styled.input`
|
|||||||
background-color: ${colors.WHITE};
|
background-color: ${colors.WHITE};
|
||||||
transition: ${TRANSITION.HOVER};
|
transition: ${TRANSITION.HOVER};
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: ${colors.INPUT_FOCUSED_BORDER};
|
||||||
|
box-shadow: 0 0px 6px 0 ${colors.INPUT_FOCUSED_SHADOW};
|
||||||
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background: ${colors.GRAY_LIGHT};
|
background: ${colors.GRAY_LIGHT};
|
||||||
|
@ -8,6 +8,7 @@ import type { Props } from '../../index';
|
|||||||
export default (props: Props) => {
|
export default (props: Props) => {
|
||||||
const { network, notification } = props.selectedAccount;
|
const { network, notification } = props.selectedAccount;
|
||||||
if (!network || !notification) return null;
|
if (!network || !notification) return null;
|
||||||
|
const blockchain = props.blockchain.find(b => b.shortcut === network.shortcut);
|
||||||
|
|
||||||
if (notification.type === 'backend') {
|
if (notification.type === 'backend') {
|
||||||
// special case: backend is down
|
// special case: backend is down
|
||||||
@ -17,6 +18,7 @@ export default (props: Props) => {
|
|||||||
type="error"
|
type="error"
|
||||||
title={notification.title}
|
title={notification.title}
|
||||||
message={notification.message}
|
message={notification.message}
|
||||||
|
isActionInProgress={blockchain && blockchain.connecting}
|
||||||
actions={
|
actions={
|
||||||
[{
|
[{
|
||||||
label: 'Connect',
|
label: 'Connect',
|
||||||
|
@ -71,4 +71,13 @@ export const FADE_IN = keyframes`
|
|||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SLIDE_DOWN = keyframes`
|
||||||
|
0% {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(0%);
|
||||||
|
}
|
||||||
`;
|
`;
|
@ -34,4 +34,7 @@ export default {
|
|||||||
|
|
||||||
LABEL_COLOR: '#A9A9A9',
|
LABEL_COLOR: '#A9A9A9',
|
||||||
TOOLTIP_BACKGROUND: '#333333',
|
TOOLTIP_BACKGROUND: '#333333',
|
||||||
|
|
||||||
|
INPUT_FOCUSED_BORDER: '#A9A9A9',
|
||||||
|
INPUT_FOCUSED_SHADOW: '#d6d7d7',
|
||||||
};
|
};
|
@ -16,6 +16,7 @@ export type BlockchainNetwork = {
|
|||||||
feeTimestamp: number,
|
feeTimestamp: number,
|
||||||
feeLevels: Array<BlockchainFeeLevel>,
|
feeLevels: Array<BlockchainFeeLevel>,
|
||||||
connected: boolean,
|
connected: boolean,
|
||||||
|
connecting: boolean,
|
||||||
block: number,
|
block: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,6 +24,26 @@ export type State = Array<BlockchainNetwork>;
|
|||||||
|
|
||||||
export const initialState: State = [];
|
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 onConnect = (state: State, action: BlockchainConnect): State => {
|
||||||
const shortcut = action.payload.coin.shortcut.toLowerCase();
|
const shortcut = action.payload.coin.shortcut.toLowerCase();
|
||||||
const network = state.find(b => b.shortcut === shortcut);
|
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);
|
const others = state.filter(b => b !== network);
|
||||||
return others.concat([{
|
return others.concat([{
|
||||||
...network,
|
...network,
|
||||||
|
block: info.block,
|
||||||
connected: true,
|
connected: true,
|
||||||
|
connecting: false,
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.concat([{
|
return state.concat([{
|
||||||
shortcut,
|
shortcut,
|
||||||
connected: true,
|
connected: true,
|
||||||
|
connecting: false,
|
||||||
block: info.block,
|
block: info.block,
|
||||||
feeTimestamp: 0,
|
feeTimestamp: 0,
|
||||||
feeLevels: [],
|
feeLevels: [],
|
||||||
@ -52,12 +76,14 @@ const onError = (state: State, action: BlockchainError): State => {
|
|||||||
return others.concat([{
|
return others.concat([{
|
||||||
...network,
|
...network,
|
||||||
connected: false,
|
connected: false,
|
||||||
|
connecting: false,
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state.concat([{
|
return state.concat([{
|
||||||
shortcut,
|
shortcut,
|
||||||
connected: false,
|
connected: false,
|
||||||
|
connecting: false,
|
||||||
block: 0,
|
block: 0,
|
||||||
feeTimestamp: 0,
|
feeTimestamp: 0,
|
||||||
feeLevels: [],
|
feeLevels: [],
|
||||||
@ -93,6 +119,8 @@ const updateFee = (state: State, shortcut: string, feeLevels: Array<BlockchainFe
|
|||||||
|
|
||||||
export default (state: State = initialState, action: Action): State => {
|
export default (state: State = initialState, action: Action): State => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case BLOCKCHAIN_ACTION.START_SUBSCRIBE:
|
||||||
|
return onStartSubscribe(state, action.shortcut);
|
||||||
case BLOCKCHAIN_EVENT.CONNECT:
|
case BLOCKCHAIN_EVENT.CONNECT:
|
||||||
return onConnect(state, action);
|
return onConnect(state, action);
|
||||||
case BLOCKCHAIN_EVENT.ERROR:
|
case BLOCKCHAIN_EVENT.ERROR:
|
||||||
|
@ -82,6 +82,7 @@ export default (state: State = initialState, action: Action): State => {
|
|||||||
case SEND.INIT:
|
case SEND.INIT:
|
||||||
case SEND.CHANGE:
|
case SEND.CHANGE:
|
||||||
case SEND.VALIDATION:
|
case SEND.VALIDATION:
|
||||||
|
case SEND.CLEAR:
|
||||||
return action.state;
|
return action.state;
|
||||||
|
|
||||||
case SEND.TOGGLE_ADVANCED:
|
case SEND.TOGGLE_ADVANCED:
|
||||||
|
@ -77,6 +77,7 @@ export default (state: State = initialState, action: Action): State => {
|
|||||||
case SEND.INIT:
|
case SEND.INIT:
|
||||||
case SEND.CHANGE:
|
case SEND.CHANGE:
|
||||||
case SEND.VALIDATION:
|
case SEND.VALIDATION:
|
||||||
|
case SEND.CLEAR:
|
||||||
return action.state;
|
return action.state;
|
||||||
|
|
||||||
case SEND.TOGGLE_ADVANCED:
|
case SEND.TOGGLE_ADVANCED:
|
||||||
|
@ -71,24 +71,6 @@ const AddAccountIconWrapper = styled.div`
|
|||||||
margin-right: 12px;
|
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`
|
const DiscoveryLoadingWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -162,7 +144,28 @@ const AccountMenu = (props: Props) => {
|
|||||||
|
|
||||||
if (discovery && discovery.completed) {
|
if (discovery && discovery.completed) {
|
||||||
const lastAccount = deviceAccounts[deviceAccounts.length - 1];
|
const lastAccount = deviceAccounts[deviceAccounts.length - 1];
|
||||||
if (lastAccount && !lastAccount.empty) {
|
if (!selected.connected) {
|
||||||
|
discoveryStatus = (
|
||||||
|
<Tooltip
|
||||||
|
maxWidth={200}
|
||||||
|
content={`To add a new account, connect ${selected.instanceLabel} device.`}
|
||||||
|
placement="bottom"
|
||||||
|
>
|
||||||
|
<Row>
|
||||||
|
<RowAddAccountWrapper disabled>
|
||||||
|
<AddAccountIconWrapper>
|
||||||
|
<Icon
|
||||||
|
icon={ICONS.PLUS}
|
||||||
|
size={24}
|
||||||
|
color={colors.TEXT_SECONDARY}
|
||||||
|
/>
|
||||||
|
</AddAccountIconWrapper>
|
||||||
|
Add account
|
||||||
|
</RowAddAccountWrapper>
|
||||||
|
</Row>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
} else if (lastAccount && !lastAccount.empty) {
|
||||||
discoveryStatus = (
|
discoveryStatus = (
|
||||||
<Row onClick={props.addAccount}>
|
<Row onClick={props.addAccount}>
|
||||||
<RowAddAccountWrapper>
|
<RowAddAccountWrapper>
|
||||||
@ -199,17 +202,6 @@ const AccountMenu = (props: Props) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (!selected.connected) {
|
|
||||||
discoveryStatus = (
|
|
||||||
<Row>
|
|
||||||
<DiscoveryStatusWrapper>
|
|
||||||
Accounts could not be loaded
|
|
||||||
<DiscoveryStatusText>
|
|
||||||
{`Connect ${selected.instanceLabel} device`}
|
|
||||||
</DiscoveryStatusText>
|
|
||||||
</DiscoveryStatusWrapper>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
discoveryStatus = (
|
discoveryStatus = (
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -8,18 +8,20 @@ import colors from 'config/colors';
|
|||||||
import { FONT_SIZE } from 'config/variables';
|
import { FONT_SIZE } from 'config/variables';
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
padding: 0px 24px 8px 19px;
|
|
||||||
border-bottom: 1px solid ${colors.DIVIDER};
|
|
||||||
background: ${colors.WHITE};
|
background: ${colors.WHITE};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Item = styled.div`
|
const Item = styled.div`
|
||||||
padding: 4px 2px;
|
padding: 6px 24px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-size: ${FONT_SIZE.BASE};
|
font-size: ${FONT_SIZE.BASE};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: ${colors.TEXT_SECONDARY};
|
color: ${colors.TEXT_SECONDARY};
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: ${colors.GRAY_LIGHT};
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Label = styled.div`
|
const Label = styled.div`
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import TrezorConnect from 'trezor-connect';
|
import TrezorConnect from 'trezor-connect';
|
||||||
|
|
||||||
|
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 Button from 'components/Button';
|
||||||
import * as deviceUtils from 'utils/device';
|
import * as deviceUtils from 'utils/device';
|
||||||
import MenuItems from './components/MenuItems';
|
import MenuItems from './components/MenuItems';
|
||||||
@ -9,11 +14,20 @@ import DeviceList from './components/DeviceList';
|
|||||||
|
|
||||||
import type { Props } from '../common';
|
import type { Props } from '../common';
|
||||||
|
|
||||||
import AsideDivider from '../Divider';
|
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);
|
||||||
|
animation: ${SLIDE_DOWN} 0.25s cubic-bezier(0.17, 0.04, 0.03, 0.94) forwards;
|
||||||
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.div``;
|
|
||||||
const ButtonWrapper = styled.div`
|
const ButtonWrapper = styled.div`
|
||||||
margin-top: 10px;
|
margin: 10px 0;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
`;
|
`;
|
||||||
@ -21,11 +35,20 @@ const StyledButton = styled(Button)`
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledDivider = styled(Divider)`
|
||||||
|
background: #fff;
|
||||||
|
color: ${COLORS.TEXT_PRIMARY};
|
||||||
|
font-weight: ${FONT_WEIGHT.MEDIUM};
|
||||||
|
font-size: ${FONT_SIZE.BASE};
|
||||||
|
border: none;
|
||||||
|
`;
|
||||||
|
|
||||||
class DeviceMenu extends PureComponent<Props> {
|
class DeviceMenu extends PureComponent<Props> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.mouseDownHandler = this.mouseDownHandler.bind(this);
|
this.mouseDownHandler = this.mouseDownHandler.bind(this);
|
||||||
this.blurHandler = this.blurHandler.bind(this);
|
this.blurHandler = this.blurHandler.bind(this);
|
||||||
|
this.myRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
@ -44,6 +67,10 @@ class DeviceMenu extends PureComponent<Props> {
|
|||||||
window.removeEventListener('mousedown', this.mouseDownHandler, false);
|
window.removeEventListener('mousedown', this.mouseDownHandler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMenuHeight(): number {
|
||||||
|
return this.myRef.current ? this.myRef.current.getBoundingClientRect().height : 0;
|
||||||
|
}
|
||||||
|
|
||||||
blurHandler(): void {
|
blurHandler(): void {
|
||||||
this.props.toggleDeviceDropdown(false);
|
this.props.toggleDeviceDropdown(false);
|
||||||
}
|
}
|
||||||
@ -77,26 +104,28 @@ class DeviceMenu extends PureComponent<Props> {
|
|||||||
return deviceUtils.isDeviceAccessible(this.props.wallet.selectedDevice);
|
return deviceUtils.isDeviceAccessible(this.props.wallet.selectedDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
myRef: { current: ?HTMLDivElement }
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { devices, onSelectDevice, forgetDevice } = this.props;
|
const { devices, onSelectDevice, forgetDevice } = this.props;
|
||||||
const { transport } = this.props.connect;
|
const { transport } = this.props.connect;
|
||||||
const { selectedDevice } = this.props.wallet;
|
const { selectedDevice } = this.props.wallet;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper ref={this.myRef}>
|
||||||
{this.showMenuItems() && <MenuItems device={selectedDevice} {...this.props} />}
|
{this.showMenuItems() && <MenuItems device={selectedDevice} {...this.props} />}
|
||||||
{this.showDivider() && <AsideDivider textLeft="Other devices" />}
|
{this.showDivider() && <StyledDivider hasBorder textLeft="Other devices" />}
|
||||||
<DeviceList
|
<DeviceList
|
||||||
devices={devices}
|
devices={devices}
|
||||||
selectedDevice={selectedDevice}
|
selectedDevice={selectedDevice}
|
||||||
onSelectDevice={onSelectDevice}
|
onSelectDevice={onSelectDevice}
|
||||||
forgetDevice={forgetDevice}
|
forgetDevice={forgetDevice}
|
||||||
/>
|
/>
|
||||||
<ButtonWrapper>
|
{deviceUtils.isWebUSB(transport) && (
|
||||||
{deviceUtils.isWebUSB(transport) && (
|
<ButtonWrapper>
|
||||||
<StyledButton isWebUsb>Check for devices</StyledButton>
|
<StyledButton isWebUsb>Check for devices</StyledButton>
|
||||||
)}
|
</ButtonWrapper>
|
||||||
</ButtonWrapper>
|
)}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,11 @@ const Wrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Divider = ({
|
const Divider = ({
|
||||||
textLeft, textRight, hasBorder = false,
|
textLeft, textRight, hasBorder = false, className,
|
||||||
}) => (
|
}) => (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
hasBorder={hasBorder}
|
hasBorder={hasBorder}
|
||||||
|
className={className}
|
||||||
>
|
>
|
||||||
<p>{textLeft}</p>
|
<p>{textLeft}</p>
|
||||||
<p>{textRight}</p>
|
<p>{textRight}</p>
|
||||||
@ -30,6 +31,7 @@ const Divider = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
Divider.propTypes = {
|
Divider.propTypes = {
|
||||||
|
className: PropTypes.string,
|
||||||
textLeft: PropTypes.string,
|
textLeft: PropTypes.string,
|
||||||
textRight: PropTypes.string,
|
textRight: PropTypes.string,
|
||||||
hasBorder: PropTypes.bool,
|
hasBorder: PropTypes.bool,
|
||||||
|
@ -60,6 +60,7 @@ const Footer = styled.div.attrs(props => ({
|
|||||||
|
|
||||||
const Body = styled.div`
|
const Body = styled.div`
|
||||||
width: 320px;
|
width: 320px;
|
||||||
|
min-height: ${props => (props.minHeight ? `${props.minHeight}px` : '0px')};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Help = styled.div`
|
const Help = styled.div`
|
||||||
@ -113,42 +114,48 @@ const TransitionMenu = (props: TransitionMenuProps): React$Element<TransitionGro
|
|||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
animationType: ?string;
|
animationType: ?string;
|
||||||
shouldRenderDeviceSelection: boolean;
|
|
||||||
clicked: boolean;
|
clicked: boolean;
|
||||||
|
bodyMinHeight: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LeftNavigation extends React.PureComponent<Props, State> {
|
class LeftNavigation extends React.PureComponent<Props, State> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.deviceMenuRef = React.createRef();
|
||||||
const { location } = this.props.router;
|
const { location } = this.props.router;
|
||||||
const hasNetwork = location && location.state && location.state.network;
|
const hasNetwork = location && location.state && location.state.network;
|
||||||
this.state = {
|
this.state = {
|
||||||
animationType: hasNetwork ? 'slide-left' : null,
|
animationType: hasNetwork ? 'slide-left' : null,
|
||||||
shouldRenderDeviceSelection: false,
|
|
||||||
clicked: false,
|
clicked: false,
|
||||||
|
bodyMinHeight: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.recalculateBodyMinHeight();
|
||||||
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps: Props) {
|
componentWillReceiveProps(nextProps: Props) {
|
||||||
const { dropdownOpened, selectedDevice } = nextProps.wallet;
|
const { selectedDevice } = nextProps.wallet;
|
||||||
const { location } = nextProps.router;
|
const { location } = nextProps.router;
|
||||||
const hasNetwork = location && location.state.network;
|
const hasNetwork = location && location.state.network;
|
||||||
const deviceReady = selectedDevice && selectedDevice.features && selectedDevice.mode === 'normal';
|
const deviceReady = selectedDevice && selectedDevice.features && selectedDevice.mode === 'normal';
|
||||||
if (dropdownOpened) {
|
|
||||||
this.setState({ shouldRenderDeviceSelection: true });
|
if (hasNetwork) {
|
||||||
} else if (hasNetwork) {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
shouldRenderDeviceSelection: false,
|
|
||||||
animationType: 'slide-left',
|
animationType: 'slide-left',
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
shouldRenderDeviceSelection: false,
|
|
||||||
animationType: deviceReady ? 'slide-right' : null,
|
animationType: deviceReady ? 'slide-right' : null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
this.recalculateBodyMinHeight();
|
||||||
|
}
|
||||||
|
|
||||||
shouldRenderAccounts() {
|
shouldRenderAccounts() {
|
||||||
const { selectedDevice } = this.props.wallet;
|
const { selectedDevice } = this.props.wallet;
|
||||||
const { location } = this.props.router;
|
const { location } = this.props.router;
|
||||||
@ -156,7 +163,6 @@ class LeftNavigation extends React.PureComponent<Props, State> {
|
|||||||
&& location
|
&& location
|
||||||
&& location.state
|
&& location.state
|
||||||
&& location.state.network
|
&& location.state.network
|
||||||
&& !this.state.shouldRenderDeviceSelection
|
|
||||||
&& this.state.animationType === 'slide-left';
|
&& this.state.animationType === 'slide-left';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,9 +172,19 @@ class LeftNavigation extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
shouldRenderCoins() {
|
shouldRenderCoins() {
|
||||||
return !this.state.shouldRenderDeviceSelection && this.state.animationType !== 'slide-left';
|
return this.state.animationType !== 'slide-left';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
recalculateBodyMinHeight() {
|
||||||
|
if (this.deviceMenuRef.current) {
|
||||||
|
this.setState({
|
||||||
|
bodyMinHeight: this.deviceMenuRef.current.getMenuHeight(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceMenuRef: { current: any };
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props } = this;
|
const { props } = this;
|
||||||
let menu;
|
let menu;
|
||||||
@ -186,7 +202,7 @@ class LeftNavigation extends React.PureComponent<Props, State> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { selectedDevice } = props.wallet;
|
const { selectedDevice, dropdownOpened } = props.wallet;
|
||||||
const isDeviceAccessible = deviceUtils.isDeviceAccessible(selectedDevice);
|
const isDeviceAccessible = deviceUtils.isDeviceAccessible(selectedDevice);
|
||||||
const walletType = selectedDevice && !selectedDevice.useEmptyPassphrase ? 'hidden' : 'standard';
|
const walletType = selectedDevice && !selectedDevice.useEmptyPassphrase ? 'hidden' : 'standard';
|
||||||
const showWalletType = selectedDevice && selectedDevice.features && selectedDevice.features.passphrase_protection;
|
const showWalletType = selectedDevice && selectedDevice.features && selectedDevice.features.passphrase_protection;
|
||||||
@ -263,8 +279,8 @@ class LeftNavigation extends React.PureComponent<Props, State> {
|
|||||||
)}
|
)}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
/>
|
/>
|
||||||
<Body>
|
<Body minHeight={this.state.bodyMinHeight}>
|
||||||
{this.state.shouldRenderDeviceSelection && <DeviceMenu {...this.props} />}
|
{dropdownOpened && <DeviceMenu ref={this.deviceMenuRef} {...this.props} />}
|
||||||
{isDeviceAccessible && menu}
|
{isDeviceAccessible && menu}
|
||||||
</Body>
|
</Body>
|
||||||
<Footer key="sticky-footer">
|
<Footer key="sticky-footer">
|
||||||
|
@ -142,17 +142,33 @@ const ToggleAdvancedSettingsButton = styled(Button)`
|
|||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1 1 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-weight: ${FONT_WEIGHT.SEMIBOLD};
|
font-weight: ${FONT_WEIGHT.SEMIBOLD};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const SendButton = styled(Button)`
|
const FormButtons = styled.div`
|
||||||
min-width: ${props => (props.isAdvancedSettingsHidden ? '50%' : '100%')};
|
display: flex;
|
||||||
word-break: break-all;
|
flex: 1 1;
|
||||||
|
|
||||||
|
|
||||||
@media screen and (max-width: ${SmallScreenWidth}) {
|
@media screen and (max-width: ${SmallScreenWidth}) {
|
||||||
margin-top: ${props => (props.isAdvancedSettingsHidden ? '10px' : 0)};
|
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)`
|
const AdvancedSettingsIcon = styled(Icon)`
|
||||||
@ -228,6 +244,7 @@ const AccountSend = (props: Props) => {
|
|||||||
onFeeLevelChange,
|
onFeeLevelChange,
|
||||||
updateFeeLevels,
|
updateFeeLevels,
|
||||||
onSend,
|
onSend,
|
||||||
|
onClear,
|
||||||
} = props.sendFormActions;
|
} = props.sendFormActions;
|
||||||
|
|
||||||
if (!device || !account || !discovery || !network || !shouldRender) {
|
if (!device || !account || !discovery || !network || !shouldRender) {
|
||||||
@ -387,24 +404,43 @@ const AccountSend = (props: Props) => {
|
|||||||
</ToggleAdvancedSettingsButton>
|
</ToggleAdvancedSettingsButton>
|
||||||
|
|
||||||
{isAdvancedSettingsHidden && (
|
{isAdvancedSettingsHidden && (
|
||||||
<SendButton
|
<FormButtons
|
||||||
isDisabled={isSendButtonDisabled}
|
|
||||||
isAdvancedSettingsHidden={isAdvancedSettingsHidden}
|
isAdvancedSettingsHidden={isAdvancedSettingsHidden}
|
||||||
onClick={() => onSend()}
|
|
||||||
>
|
>
|
||||||
{sendButtonText}
|
<ClearButton
|
||||||
</SendButton>
|
isWhite
|
||||||
|
onClick={() => onClear()}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</ClearButton>
|
||||||
|
<SendButton
|
||||||
|
isDisabled={isSendButtonDisabled}
|
||||||
|
onClick={() => onSend()}
|
||||||
|
>
|
||||||
|
{sendButtonText}
|
||||||
|
</SendButton>
|
||||||
|
</FormButtons>
|
||||||
)}
|
)}
|
||||||
</ToggleAdvancedSettingsWrapper>
|
</ToggleAdvancedSettingsWrapper>
|
||||||
|
|
||||||
{advanced && (
|
{advanced && (
|
||||||
<AdvancedForm {...props}>
|
<AdvancedForm {...props}>
|
||||||
<SendButton
|
<FormButtons
|
||||||
isDisabled={isSendButtonDisabled}
|
isAdvancedSettingsHidden={isAdvancedSettingsHidden}
|
||||||
onClick={() => onSend()}
|
|
||||||
>
|
>
|
||||||
{sendButtonText}
|
<ClearButton
|
||||||
</SendButton>
|
isWhite
|
||||||
|
onClick={() => onClear()}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</ClearButton>
|
||||||
|
<SendButton
|
||||||
|
isDisabled={isSendButtonDisabled}
|
||||||
|
onClick={() => onSend()}
|
||||||
|
>
|
||||||
|
{sendButtonText}
|
||||||
|
</SendButton>
|
||||||
|
</FormButtons>
|
||||||
</AdvancedForm>
|
</AdvancedForm>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -139,17 +139,33 @@ const ToggleAdvancedSettingsButton = styled(Button)`
|
|||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: 1 1 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font-weight: ${FONT_WEIGHT.SEMIBOLD};
|
font-weight: ${FONT_WEIGHT.SEMIBOLD};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const SendButton = styled(Button)`
|
const FormButtons = styled.div`
|
||||||
min-width: ${props => (props.isAdvancedSettingsHidden ? '50%' : '100%')};
|
display: flex;
|
||||||
word-break: break-all;
|
flex: 1 1;
|
||||||
|
|
||||||
|
|
||||||
@media screen and (max-width: ${SmallScreenWidth}) {
|
@media screen and (max-width: ${SmallScreenWidth}) {
|
||||||
margin-top: ${props => (props.isAdvancedSettingsHidden ? '10px' : 0)};
|
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)`
|
const AdvancedSettingsIcon = styled(Icon)`
|
||||||
@ -214,6 +230,7 @@ const AccountSend = (props: Props) => {
|
|||||||
onFeeLevelChange,
|
onFeeLevelChange,
|
||||||
updateFeeLevels,
|
updateFeeLevels,
|
||||||
onSend,
|
onSend,
|
||||||
|
onClear,
|
||||||
} = props.sendFormActions;
|
} = props.sendFormActions;
|
||||||
|
|
||||||
if (!device || !account || !discovery || !network || !shouldRender) {
|
if (!device || !account || !discovery || !network || !shouldRender) {
|
||||||
@ -359,24 +376,43 @@ const AccountSend = (props: Props) => {
|
|||||||
</ToggleAdvancedSettingsButton>
|
</ToggleAdvancedSettingsButton>
|
||||||
|
|
||||||
{isAdvancedSettingsHidden && (
|
{isAdvancedSettingsHidden && (
|
||||||
<SendButton
|
<FormButtons
|
||||||
isDisabled={isSendButtonDisabled}
|
|
||||||
isAdvancedSettingsHidden={isAdvancedSettingsHidden}
|
isAdvancedSettingsHidden={isAdvancedSettingsHidden}
|
||||||
onClick={() => onSend()}
|
|
||||||
>
|
>
|
||||||
{sendButtonText}
|
<ClearButton
|
||||||
</SendButton>
|
isWhite
|
||||||
|
onClick={() => onClear()}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</ClearButton>
|
||||||
|
<SendButton
|
||||||
|
isDisabled={isSendButtonDisabled}
|
||||||
|
onClick={() => onSend()}
|
||||||
|
>
|
||||||
|
{sendButtonText}
|
||||||
|
</SendButton>
|
||||||
|
</FormButtons>
|
||||||
)}
|
)}
|
||||||
</ToggleAdvancedSettingsWrapper>
|
</ToggleAdvancedSettingsWrapper>
|
||||||
|
|
||||||
{advanced && (
|
{advanced && (
|
||||||
<AdvancedForm {...props}>
|
<AdvancedForm {...props}>
|
||||||
<SendButton
|
<FormButtons
|
||||||
isDisabled={isSendButtonDisabled}
|
isAdvancedSettingsHidden={isAdvancedSettingsHidden}
|
||||||
onClick={() => onSend()}
|
|
||||||
>
|
>
|
||||||
{sendButtonText}
|
<ClearButton
|
||||||
</SendButton>
|
isWhite
|
||||||
|
onClick={() => onClear()}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</ClearButton>
|
||||||
|
<SendButton
|
||||||
|
isDisabled={isSendButtonDisabled}
|
||||||
|
onClick={() => onSend()}
|
||||||
|
>
|
||||||
|
{sendButtonText}
|
||||||
|
</SendButton>
|
||||||
|
</FormButtons>
|
||||||
</AdvancedForm>
|
</AdvancedForm>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user