summaryrefslogtreecommitdiffhomepage
path: root/gui
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2019-06-27 13:34:55 +0200
committerAndrej Mihajlov <and@mullvad.net>2019-06-27 20:01:18 +0200
commit55ee652e4ef13faea40d4f202dfa66d77a01c813 (patch)
tree32419bf246017da10c03d149a210c96a6d18c09b /gui
parent7068c166b53b0a24dfcffa2c31c30bd120816938 (diff)
downloadmullvadvpn-55ee652e4ef13faea40d4f202dfa66d77a01c813.tar.xz
mullvadvpn-55ee652e4ef13faea40d4f202dfa66d77a01c813.zip
Refactor connection panel into container
Diffstat (limited to 'gui')
-rw-r--r--gui/src/renderer/components/Connect.tsx52
-rw-r--r--gui/src/renderer/components/ConnectionPanel.tsx (renamed from gui/src/renderer/components/ConnectionInfo.tsx)95
-rw-r--r--gui/src/renderer/components/ConnectionPanelDisclosure.tsx (renamed from gui/src/renderer/components/ConnectionInfoDisclosure.tsx)28
-rw-r--r--gui/src/renderer/components/TunnelControl.tsx51
-rw-r--r--gui/src/renderer/containers/ConnectPage.tsx10
-rw-r--r--gui/src/renderer/containers/ConnectionPanelContainer.tsx75
-rw-r--r--gui/src/renderer/redux/userinterface/actions.ts10
-rw-r--r--gui/src/renderer/redux/userinterface/reducers.ts8
8 files changed, 137 insertions, 192 deletions
diff --git a/gui/src/renderer/components/Connect.tsx b/gui/src/renderer/components/Connect.tsx
index 60fca1df50..b39f09e705 100644
--- a/gui/src/renderer/components/Connect.tsx
+++ b/gui/src/renderer/components/Connect.tsx
@@ -1,7 +1,6 @@
import * as React from 'react';
import { Component, Styles, View } from 'reactxp';
import { links } from '../../config.json';
-import { ITunnelEndpoint, parseSocketAddress } from '../../shared/daemon-rpc-types';
import AccountExpiry from '../lib/account-expiry';
import { AuthFailureKind, parseAuthFailure } from '../lib/auth-failure';
import { IConnectionReduxState } from '../redux/connection/reducers';
@@ -12,21 +11,19 @@ import ImageView from './ImageView';
import { Container, Header, Layout } from './Layout';
import Map, { MarkerStyle, ZoomLevel } from './Map';
import NotificationArea from './NotificationArea';
-import TunnelControl, { IBridgeData, IRelayInAddress, IRelayOutAddress } from './TunnelControl';
+import TunnelControl from './TunnelControl';
interface IProps {
connection: IConnectionReduxState;
version: IVersionReduxState;
accountExpiry?: AccountExpiry;
selectedRelayName: string;
- connectionInfoOpen: boolean;
blockWhenDisconnected: boolean;
onSettings: () => void;
onSelectLocation: () => void;
onConnect: () => void;
onDisconnect: () => void;
onExternalLink: (url: string) => void;
- onToggleConnectionInfo: (value: boolean) => void;
}
type MarkerOrSpinner = 'marker' | 'spinner';
@@ -148,22 +145,6 @@ export default class Connect extends Component<IProps, IState> {
}
private renderMap() {
- const status = this.props.connection.status;
-
- const relayOutAddress: IRelayOutAddress = {
- ipv4: this.props.connection.ipv4,
- ipv6: this.props.connection.ipv6,
- };
- const relayInAddress: IRelayInAddress | undefined =
- (status.state === 'connecting' || status.state === 'connected') && status.details
- ? this.tunnelEndpointToRelayInAddress(status.details)
- : undefined;
-
- const bridgeData: IBridgeData | undefined =
- (status.state === 'connecting' || status.state === 'connected') && status.details
- ? this.tunnelEndpointToBridgeData(status.details)
- : undefined;
-
return (
<View style={styles.connect}>
<Map style={styles.map} {...this.getMapProps()} />
@@ -180,16 +161,9 @@ export default class Connect extends Component<IProps, IState> {
selectedRelayName={this.props.selectedRelayName}
city={this.props.connection.city}
country={this.props.connection.country}
- hostname={this.props.connection.hostname}
- defaultConnectionInfoOpen={this.props.connectionInfoOpen}
- relayInAddress={relayInAddress}
- bridge={bridgeData}
- bridgeHostname={this.props.connection.bridgeHostname}
- relayOutAddress={relayOutAddress}
onConnect={this.props.onConnect}
onDisconnect={this.props.onDisconnect}
onSelectLocation={this.props.onSelectLocation}
- onToggleConnectionInfo={this.props.onToggleConnectionInfo}
/>
<NotificationArea
@@ -321,28 +295,4 @@ export default class Connect extends Component<IProps, IState> {
? 'spinner'
: 'marker';
}
-
- private tunnelEndpointToRelayInAddress(tunnelEndpoint: ITunnelEndpoint): IRelayInAddress {
- const socketAddr = parseSocketAddress(tunnelEndpoint.address);
- return {
- ip: socketAddr.host,
- port: socketAddr.port,
- protocol: tunnelEndpoint.protocol,
- tunnelType: tunnelEndpoint.tunnelType,
- };
- }
-
- private tunnelEndpointToBridgeData(endpoint: ITunnelEndpoint): IBridgeData | undefined {
- if (!endpoint.proxy) {
- return undefined;
- }
-
- const socketAddr = parseSocketAddress(endpoint.proxy.address);
- return {
- ip: socketAddr.host,
- port: socketAddr.port,
- protocol: endpoint.proxy.protocol,
- bridgeType: endpoint.proxy.proxyType,
- };
- }
}
diff --git a/gui/src/renderer/components/ConnectionInfo.tsx b/gui/src/renderer/components/ConnectionPanel.tsx
index 2c6796f7fc..9992d3bf73 100644
--- a/gui/src/renderer/components/ConnectionInfo.tsx
+++ b/gui/src/renderer/components/ConnectionPanel.tsx
@@ -1,10 +1,45 @@
import * as React from 'react';
import { Component, Styles, Text, Types, View } from 'reactxp';
import { sprintf } from 'sprintf-js';
-import { proxyTypeToString, TunnelType, tunnelTypeToString } from '../../shared/daemon-rpc-types';
+import {
+ ProxyType,
+ proxyTypeToString,
+ RelayProtocol,
+ TunnelType,
+ tunnelTypeToString,
+} from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
-import { default as ConnectionInfoDisclosure } from './ConnectionInfoDisclosure';
-import { IBridgeData } from './TunnelControl';
+import { default as ConnectionPanelDisclosure } from '../components/ConnectionPanelDisclosure';
+
+export interface IEndpoint {
+ ip: string;
+ port: number;
+ protocol: RelayProtocol;
+}
+
+export interface IInAddress extends IEndpoint {
+ tunnelType: TunnelType;
+}
+
+export interface IBridgeData extends IEndpoint {
+ bridgeType: ProxyType;
+}
+
+export interface IOutAddress {
+ ipv4?: string;
+ ipv6?: string;
+}
+
+interface IProps {
+ isOpen: boolean;
+ hostname?: string;
+ bridgeHostname?: string;
+ inAddress?: IInAddress;
+ bridgeInfo?: IBridgeData;
+ outAddress?: IOutAddress;
+ onToggle: () => void;
+ style?: Types.ViewStyleRuleSet | Types.ViewStyleRuleSet[];
+}
const styles = {
row: Styles.createViewStyle({
@@ -32,42 +67,7 @@ const styles = {
}),
};
-interface IInAddress {
- ip: string;
- port: number;
- protocol: string;
- tunnelType: TunnelType;
-}
-
-interface IOutAddress {
- ipv4?: string;
- ipv6?: string;
-}
-
-interface IProps {
- hostname?: string;
- bridgeHostname?: string;
- inAddress?: IInAddress;
- bridgeInfo?: IBridgeData;
- outAddress?: IOutAddress;
- defaultOpen?: boolean;
- style?: Types.ViewStyleRuleSet | Types.ViewStyleRuleSet[];
- onToggle?: (isOpen: boolean) => void;
-}
-
-interface IState {
- isOpen: boolean;
-}
-
-export default class ConnectionInfo extends Component<IProps, IState> {
- constructor(props: IProps) {
- super(props);
-
- this.state = {
- isOpen: props.defaultOpen === true,
- };
- }
-
+export default class ConnectionPanel extends Component<IProps> {
public render() {
const { inAddress, outAddress, bridgeInfo } = this.props;
const entryPoint = bridgeInfo && inAddress ? bridgeInfo : inAddress;
@@ -76,13 +76,13 @@ export default class ConnectionInfo extends Component<IProps, IState> {
<View style={this.props.style}>
{this.props.hostname && (
<View style={styles.header}>
- <ConnectionInfoDisclosure defaultOpen={this.props.defaultOpen} onToggle={this.onToggle}>
+ <ConnectionPanelDisclosure pointsUp={this.props.isOpen} onToggle={this.props.onToggle}>
{this.hostnameLine()}
- </ConnectionInfoDisclosure>
+ </ConnectionPanelDisclosure>
</View>
)}
- {this.state.isOpen && this.props.hostname && (
+ {this.props.isOpen && this.props.hostname && (
<React.Fragment>
{this.props.inAddress && (
<View style={styles.row}>
@@ -159,15 +159,4 @@ export default class ConnectionInfo extends Component<IProps, IState> {
return '';
}
}
-
- private onToggle = (isOpen: boolean) => {
- this.setState(
- (state) => ({ ...state, isOpen }),
- () => {
- if (this.props.onToggle) {
- this.props.onToggle(isOpen);
- }
- },
- );
- };
}
diff --git a/gui/src/renderer/components/ConnectionInfoDisclosure.tsx b/gui/src/renderer/components/ConnectionPanelDisclosure.tsx
index 3489a639dd..17c3dc9919 100644
--- a/gui/src/renderer/components/ConnectionInfoDisclosure.tsx
+++ b/gui/src/renderer/components/ConnectionPanelDisclosure.tsx
@@ -22,41 +22,39 @@ const styles = {
};
interface IProps {
- onToggle?: (isOpen: boolean) => void;
- defaultOpen?: boolean;
+ pointsUp: boolean;
+ onToggle?: () => void;
children: React.ReactText;
style?: Types.ViewStyleRuleSet | Types.ViewStyleRuleSet[];
}
interface IState {
isHovered: boolean;
- isOpen: boolean;
}
-export default class ConnectionInfoDisclosure extends Component<IProps, IState> {
+export default class ConnectionPanelDisclosure extends Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = {
isHovered: false,
- isOpen: props.defaultOpen === true,
};
}
public render() {
const tintColor = this.state.isHovered ? 'rgb(255, 255, 255)' : 'rgb(255, 255, 255, 0.4)';
const textHoverStyle =
- this.state.isOpen || this.state.isHovered ? styles.caption.hovered : undefined;
+ this.props.pointsUp || this.state.isHovered ? styles.caption.hovered : undefined;
return (
<View
style={[styles.container, this.props.style]}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
- onPress={this.onToggle}>
+ onPress={this.props.onToggle}>
<Text style={[styles.caption.base, textHoverStyle]}>{this.props.children}</Text>
<ImageView
- source={this.state.isOpen ? 'icon-chevron-up' : 'icon-chevron-down'}
+ source={this.props.pointsUp ? 'icon-chevron-up' : 'icon-chevron-down'}
width={24}
height={24}
tintColor={tintColor}
@@ -72,18 +70,4 @@ export default class ConnectionInfoDisclosure extends Component<IProps, IState>
private onMouseLeave = () => {
this.setState({ isHovered: false });
};
-
- private onToggle = () => {
- this.setState(
- (state) => ({
- ...state,
- isOpen: !state.isOpen,
- }),
- () => {
- if (this.props.onToggle) {
- this.props.onToggle(this.state.isOpen);
- }
- },
- );
- };
}
diff --git a/gui/src/renderer/components/TunnelControl.tsx b/gui/src/renderer/components/TunnelControl.tsx
index ed062c9f0d..ffb7ac2479 100644
--- a/gui/src/renderer/components/TunnelControl.tsx
+++ b/gui/src/renderer/components/TunnelControl.tsx
@@ -1,51 +1,20 @@
import * as React from 'react';
import { Component, Styles, Text, Types, View } from 'reactxp';
import { colors } from '../../config.json';
-import {
- ProxyType,
- RelayProtocol,
- TunnelStateTransition,
- TunnelType,
-} from '../../shared/daemon-rpc-types';
+import { TunnelStateTransition } from '../../shared/daemon-rpc-types';
import { cities, countries, messages, relayLocations } from '../../shared/gettext';
+import ConnectionPanelContainer from '../containers/ConnectionPanelContainer';
import * as AppButton from './AppButton';
-import ConnectionInfo from './ConnectionInfo';
import SecuredLabel, { SecuredDisplayStyle } from './SecuredLabel';
-export interface IEndpoint {
- ip: string;
- port: number;
- protocol: RelayProtocol;
-}
-
-export interface IRelayInAddress extends IEndpoint {
- tunnelType: TunnelType;
-}
-
-export interface IBridgeData extends IEndpoint {
- bridgeType: ProxyType;
-}
-
-export interface IRelayOutAddress {
- ipv4?: string;
- ipv6?: string;
-}
-
interface ITunnelControlProps {
tunnelState: TunnelStateTransition;
selectedRelayName: string;
city?: string;
country?: string;
- hostname?: string;
- defaultConnectionInfoOpen?: boolean;
- relayInAddress?: IRelayInAddress;
- relayOutAddress?: IRelayOutAddress;
- bridge?: IBridgeData;
- bridgeHostname?: string;
onConnect: () => void;
onDisconnect: () => void;
onSelectLocation: () => void;
- onToggleConnectionInfo: (value: boolean) => void;
}
const styles = {
@@ -157,18 +126,6 @@ export default class TunnelControl extends Component<ITunnelControlProps> {
<View style={styles.footer}>{children}</View>
);
- const connectionDetails = (
- <ConnectionInfo
- hostname={this.props.hostname}
- bridgeHostname={this.props.bridgeHostname}
- inAddress={this.props.relayInAddress}
- bridgeInfo={this.props.bridge}
- outAddress={this.props.relayOutAddress}
- defaultOpen={this.props.defaultConnectionInfoOpen}
- onToggle={this.props.onToggleConnectionInfo}
- />
- );
-
let state = this.props.tunnelState.state;
switch (this.props.tunnelState.state) {
@@ -208,7 +165,7 @@ export default class TunnelControl extends Component<ITunnelControlProps> {
<City />
<Country />
</Location>
- {connectionDetails}
+ <ConnectionPanelContainer />
</Body>
<Footer>
<SwitchLocation />
@@ -225,7 +182,7 @@ export default class TunnelControl extends Component<ITunnelControlProps> {
<City />
<Country />
</Location>
- {connectionDetails}
+ <ConnectionPanelContainer />
</Body>
<Footer>
<SwitchLocation />
diff --git a/gui/src/renderer/containers/ConnectPage.tsx b/gui/src/renderer/containers/ConnectPage.tsx
index 2e22ca9fab..3669171f89 100644
--- a/gui/src/renderer/containers/ConnectPage.tsx
+++ b/gui/src/renderer/containers/ConnectPage.tsx
@@ -11,13 +11,10 @@ import {
} from '../../shared/gettext';
import Connect from '../components/Connect';
import AccountExpiry from '../lib/account-expiry';
-import userInterfaceActions from '../redux/userinterface/actions';
-
+import { IRelayLocationRedux, RelaySettingsRedux } from '../redux/settings/reducers';
import { IReduxState, ReduxDispatch } from '../redux/store';
import { ISharedRouteProps } from '../routes';
-import { IRelayLocationRedux, RelaySettingsRedux } from '../redux/settings/reducers';
-
function getRelayName(
relaySettings: RelaySettingsRedux,
relayLocations: IRelayLocationRedux[],
@@ -79,19 +76,14 @@ const mapStateToProps = (state: IReduxState, props: ISharedRouteProps) => {
selectedRelayName: getRelayName(state.settings.relaySettings, state.settings.relayLocations),
connection: state.connection,
version: state.version,
- connectionInfoOpen: state.userInterface.connectionInfoOpen,
blockWhenDisconnected: state.settings.blockWhenDisconnected,
};
};
const mapDispatchToProps = (dispatch: ReduxDispatch, props: ISharedRouteProps) => {
- const userInterface = bindActionCreators(userInterfaceActions, dispatch);
const history = bindActionCreators({ push }, dispatch);
return {
- onToggleConnectionInfo: (isOpen: boolean) => {
- userInterface.updateConnectionInfoOpen(isOpen);
- },
onSettings: () => {
history.push('/settings');
},
diff --git a/gui/src/renderer/containers/ConnectionPanelContainer.tsx b/gui/src/renderer/containers/ConnectionPanelContainer.tsx
new file mode 100644
index 0000000000..77b164c65b
--- /dev/null
+++ b/gui/src/renderer/containers/ConnectionPanelContainer.tsx
@@ -0,0 +1,75 @@
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import { ITunnelEndpoint, parseSocketAddress } from '../../shared/daemon-rpc-types';
+import ConnectionPanel, {
+ IBridgeData,
+ IInAddress,
+ IOutAddress,
+} from '../components/ConnectionPanel';
+import { IReduxState, ReduxDispatch } from '../redux/store';
+import userInterfaceActions from '../redux/userinterface/actions';
+
+function tunnelEndpointToRelayInAddress(tunnelEndpoint: ITunnelEndpoint): IInAddress {
+ const socketAddr = parseSocketAddress(tunnelEndpoint.address);
+ return {
+ ip: socketAddr.host,
+ port: socketAddr.port,
+ protocol: tunnelEndpoint.protocol,
+ tunnelType: tunnelEndpoint.tunnelType,
+ };
+}
+
+function tunnelEndpointToBridgeData(endpoint: ITunnelEndpoint): IBridgeData | undefined {
+ if (!endpoint.proxy) {
+ return undefined;
+ }
+
+ const socketAddr = parseSocketAddress(endpoint.proxy.address);
+ return {
+ ip: socketAddr.host,
+ port: socketAddr.port,
+ protocol: endpoint.proxy.protocol,
+ bridgeType: endpoint.proxy.proxyType,
+ };
+}
+
+const mapStateToProps = (state: IReduxState) => {
+ const status = state.connection.status;
+
+ const outAddress: IOutAddress = {
+ ipv4: state.connection.ipv4,
+ ipv6: state.connection.ipv6,
+ };
+
+ const inAddress: IInAddress | undefined =
+ (status.state === 'connecting' || status.state === 'connected') && status.details
+ ? tunnelEndpointToRelayInAddress(status.details)
+ : undefined;
+
+ const bridgeInfo: IBridgeData | undefined =
+ (status.state === 'connecting' || status.state === 'connected') && status.details
+ ? tunnelEndpointToBridgeData(status.details)
+ : undefined;
+
+ return {
+ isOpen: state.userInterface.connectionPanelVisible,
+ hostname: state.connection.hostname,
+ bridgeHostname: state.connection.bridgeHostname,
+ inAddress,
+ bridgeInfo,
+ outAddress,
+ };
+};
+
+const mapDispatchToProps = (dispatch: ReduxDispatch) => {
+ const userInterface = bindActionCreators(userInterfaceActions, dispatch);
+
+ return {
+ onToggle: userInterface.toggleConnectionPanel,
+ };
+};
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps,
+)(ConnectionPanel);
diff --git a/gui/src/renderer/redux/userinterface/actions.ts b/gui/src/renderer/redux/userinterface/actions.ts
index 724f53883d..0af66cd365 100644
--- a/gui/src/renderer/redux/userinterface/actions.ts
+++ b/gui/src/renderer/redux/userinterface/actions.ts
@@ -4,8 +4,7 @@ export interface IUpdateWindowArrowPositionAction {
}
export interface IUpdateConnectionInfoOpenAction {
- type: 'UPDATE_CONNECTION_INFO_OPEN';
- isOpen: boolean;
+ type: 'TOGGLE_CONNECTION_PANEL';
}
export type UserInterfaceAction =
@@ -19,11 +18,10 @@ function updateWindowArrowPosition(arrowPosition: number): IUpdateWindowArrowPos
};
}
-function updateConnectionInfoOpen(isOpen: boolean): IUpdateConnectionInfoOpenAction {
+function toggleConnectionPanel(): IUpdateConnectionInfoOpenAction {
return {
- type: 'UPDATE_CONNECTION_INFO_OPEN',
- isOpen,
+ type: 'TOGGLE_CONNECTION_PANEL',
};
}
-export default { updateWindowArrowPosition, updateConnectionInfoOpen };
+export default { updateWindowArrowPosition, toggleConnectionPanel };
diff --git a/gui/src/renderer/redux/userinterface/reducers.ts b/gui/src/renderer/redux/userinterface/reducers.ts
index 75005fd423..c6e7aafde8 100644
--- a/gui/src/renderer/redux/userinterface/reducers.ts
+++ b/gui/src/renderer/redux/userinterface/reducers.ts
@@ -2,11 +2,11 @@ import { ReduxAction } from '../store';
export interface IUserInterfaceReduxState {
arrowPosition?: number;
- connectionInfoOpen: boolean;
+ connectionPanelVisible: boolean;
}
const initialState: IUserInterfaceReduxState = {
- connectionInfoOpen: false,
+ connectionPanelVisible: false,
};
export default function(
@@ -17,8 +17,8 @@ export default function(
case 'UPDATE_WINDOW_ARROW_POSITION':
return { ...state, arrowPosition: action.arrowPosition };
- case 'UPDATE_CONNECTION_INFO_OPEN':
- return { ...state, connectionInfoOpen: action.isOpen };
+ case 'TOGGLE_CONNECTION_PANEL':
+ return { ...state, connectionPanelVisible: !state.connectionPanelVisible };
default:
return state;