diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2020-02-06 16:20:41 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2020-02-06 16:20:41 +0100 |
| commit | 42442bb8701b2e976dc73e4b4d3a1308732cdcab (patch) | |
| tree | 2c50a37f4de3b574e40acab9342dcbaee7d6d983 | |
| parent | 033e58637a99a84a7ace29ff1c23bf7c3b456d48 (diff) | |
| parent | 17bf4b6afdaff028ffc8b11d16a8e4b0e50a1a16 (diff) | |
| download | mullvadvpn-42442bb8701b2e976dc73e4b4d3a1308732cdcab.tar.xz mullvadvpn-42442bb8701b2e976dc73e4b4d3a1308732cdcab.zip | |
Merge branch 'desktop-add-reconnect-button'
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rw-r--r-- | gui/assets/images/icon-reload.svg | 1 | ||||
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 4 | ||||
| -rw-r--r-- | gui/src/main/index.ts | 1 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 4 | ||||
| -rw-r--r-- | gui/src/renderer/components/Connect.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/TunnelControl.tsx | 37 | ||||
| -rw-r--r-- | gui/src/renderer/containers/ConnectPage.tsx | 7 | ||||
| -rw-r--r-- | gui/src/shared/ipc-event-channel.ts | 5 |
9 files changed, 59 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 8042ac35e5..06743eb420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ Line wrap the file at 100 chars. Th ## [Unreleased] +### Added +- Add reconnect button to the desktop app + ### Changed - Change project copyright and company name from Amagicom AB to Mullvad VPN AB - Only reconnect when settings change if a relevant tunnel protocol is used. diff --git a/gui/assets/images/icon-reload.svg b/gui/assets/images/icon-reload.svg new file mode 100644 index 0000000000..33c7e5ec2c --- /dev/null +++ b/gui/assets/images/icon-reload.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="feather feather-rotate-cw"><polyline points="23 4 23 10 17 10"></polyline><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path></svg>
\ No newline at end of file diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index 78748b70ab..7491b20901 100644 --- a/gui/src/main/daemon-rpc.ts +++ b/gui/src/main/daemon-rpc.ts @@ -496,6 +496,10 @@ export class DaemonRpc { await this.transport.send('disconnect'); } + public async reconnectTunnel(): Promise<void> { + await this.transport.send('reconnect'); + } + public async getLocation(): Promise<ILocation | undefined> { const response = await this.transport.send('get_current_location', [], NETWORK_CALL_TIMEOUT); try { diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index a335a9f372..6663a5574e 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -943,6 +943,7 @@ class ApplicationMain { IpcMainEventChannel.tunnel.handleConnect(() => this.daemonRpc.connectTunnel()); IpcMainEventChannel.tunnel.handleDisconnect(() => this.daemonRpc.disconnectTunnel()); + IpcMainEventChannel.tunnel.handleReconnect(() => this.daemonRpc.reconnectTunnel()); IpcMainEventChannel.guiSettings.handleEnableSystemNotifications((flag: boolean) => { this.guiSettings.enableSystemNotifications = flag; diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index 5fb48f701f..58243ce22a 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -276,6 +276,10 @@ export default class AppRenderer { return IpcRendererEventChannel.tunnel.disconnect(); } + public reconnectTunnel(): Promise<void> { + return IpcRendererEventChannel.tunnel.reconnect(); + } + public updateRelaySettings(relaySettings: RelaySettingsUpdate) { return IpcRendererEventChannel.settings.updateRelaySettings(relaySettings); } diff --git a/gui/src/renderer/components/Connect.tsx b/gui/src/renderer/components/Connect.tsx index 7f73fb7ea0..4cb63c6a5b 100644 --- a/gui/src/renderer/components/Connect.tsx +++ b/gui/src/renderer/components/Connect.tsx @@ -23,6 +23,7 @@ interface IProps { onSelectLocation: () => void; onConnect: () => void; onDisconnect: () => void; + onReconnect: () => void; onExternalLinkWithAuth: (url: string) => Promise<void>; } @@ -163,6 +164,7 @@ export default class Connect extends Component<IProps, IState> { country={this.props.connection.country} onConnect={this.props.onConnect} onDisconnect={this.props.onDisconnect} + onReconnect={this.props.onReconnect} onSelectLocation={this.props.onSelectLocation} /> diff --git a/gui/src/renderer/components/TunnelControl.tsx b/gui/src/renderer/components/TunnelControl.tsx index 700603bd2e..5fbfaebc86 100644 --- a/gui/src/renderer/components/TunnelControl.tsx +++ b/gui/src/renderer/components/TunnelControl.tsx @@ -5,6 +5,7 @@ import { TunnelState } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; import ConnectionPanelContainer from '../containers/ConnectionPanelContainer'; import * as AppButton from './AppButton'; +import ImageView from './ImageView'; import SecuredLabel, { SecuredDisplayStyle } from './SecuredLabel'; interface ITunnelControlProps { @@ -14,6 +15,7 @@ interface ITunnelControlProps { country?: string; onConnect: () => void; onDisconnect: () => void; + onReconnect: () => void; onSelectLocation: () => void; } @@ -58,6 +60,16 @@ const styles = { letterSpacing: -0.9, color: colors.white, }), + button_row: Styles.createViewStyle({ + flexDirection: 'row', + }), + large_button: Styles.createViewStyle({ + flex: 1, + }), + reconnect_button: Styles.createViewStyle({ + marginLeft: 16, + paddingHorizontal: 12, + }), }; export default class TunnelControl extends Component<ITunnelControlProps> { @@ -94,17 +106,23 @@ export default class TunnelControl extends Component<ITunnelControlProps> { ); const Disconnect = () => ( - <AppButton.RedTransparentButton onPress={this.props.onDisconnect}> + <AppButton.RedTransparentButton onPress={this.props.onDisconnect} style={styles.large_button}> {messages.pgettext('tunnel-control', 'Disconnect')} </AppButton.RedTransparentButton> ); const Cancel = () => ( - <AppButton.RedTransparentButton onPress={this.props.onDisconnect}> + <AppButton.RedTransparentButton onPress={this.props.onDisconnect} style={styles.large_button}> {messages.pgettext('tunnel-control', 'Cancel')} </AppButton.RedTransparentButton> ); + const Reconnect = () => ( + <AppButton.TransparentButton onPress={this.props.onReconnect} style={styles.reconnect_button}> + <ImageView height={22} width={22} source="icon-reload" tintColor="white" /> + </AppButton.TransparentButton> + ); + const Secured = ({ displayStyle }: { displayStyle: SecuredDisplayStyle }) => ( <SecuredLabel style={styles.status_security} displayStyle={displayStyle} /> ); @@ -148,7 +166,10 @@ export default class TunnelControl extends Component<ITunnelControlProps> { </Body> <Footer> <SwitchLocation /> - <Cancel /> + <View style={styles.button_row}> + <Cancel /> + <Reconnect /> + </View> </Footer> </Wrapper> ); @@ -165,7 +186,10 @@ export default class TunnelControl extends Component<ITunnelControlProps> { </Body> <Footer> <SwitchLocation /> - <Disconnect /> + <View style={styles.button_row}> + <Disconnect /> + <Reconnect /> + </View> </Footer> </Wrapper> ); @@ -178,7 +202,10 @@ export default class TunnelControl extends Component<ITunnelControlProps> { </Body> <Footer> <SwitchLocation /> - <Cancel /> + <View style={styles.button_row}> + <Cancel /> + <Reconnect /> + </View> </Footer> </Wrapper> ); diff --git a/gui/src/renderer/containers/ConnectPage.tsx b/gui/src/renderer/containers/ConnectPage.tsx index e5261a161a..e4c37f19cc 100644 --- a/gui/src/renderer/containers/ConnectPage.tsx +++ b/gui/src/renderer/containers/ConnectPage.tsx @@ -99,6 +99,13 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => { log.error(`Failed to disconnect the tunnel: ${error.message}`); } }, + onReconnect: async () => { + try { + await props.app.reconnectTunnel(); + } catch (error) { + log.error(`Failed to reconnect the tunnel: ${error.message}`); + } + }, onExternalLinkWithAuth: (url: string) => props.app.openLinkWithAuth(url), }; }; diff --git a/gui/src/shared/ipc-event-channel.ts b/gui/src/shared/ipc-event-channel.ts index a612660c99..5502a6698a 100644 --- a/gui/src/shared/ipc-event-channel.ts +++ b/gui/src/shared/ipc-event-channel.ts @@ -56,11 +56,13 @@ interface IReceiver<T> { interface ITunnelMethods extends IReceiver<TunnelState> { connect(): Promise<void>; disconnect(): Promise<void>; + reconnect(): Promise<void>; } interface ITunnelHandlers extends ISender<TunnelState> { handleConnect(fn: () => Promise<void>): void; handleDisconnect(fn: () => Promise<void>): void; + handleReconnect(fn: () => Promise<void>): void; } interface ISettingsMethods extends IReceiver<ISettings> { @@ -150,6 +152,7 @@ const DAEMON_DISCONNECTED = 'daemon-disconnected'; const TUNNEL_STATE_CHANGED = 'tunnel-state-changed'; const CONNECT_TUNNEL = 'connect-tunnel'; const DISCONNECT_TUNNEL = 'disconnect-tunnel'; +const RECONNECT_TUNNEL = 'reconnect-tunnel'; const SETTINGS_CHANGED = 'settings-changed'; const SET_ALLOW_LAN = 'set-allow-lan'; @@ -223,6 +226,7 @@ export class IpcRendererEventChannel { listen: listen(TUNNEL_STATE_CHANGED), connect: requestSender(CONNECT_TUNNEL), disconnect: requestSender(DISCONNECT_TUNNEL), + reconnect: requestSender(RECONNECT_TUNNEL), }; public static settings: ISettingsMethods = { @@ -315,6 +319,7 @@ export class IpcMainEventChannel { notify: sender(TUNNEL_STATE_CHANGED), handleConnect: requestHandler(CONNECT_TUNNEL), handleDisconnect: requestHandler(DISCONNECT_TUNNEL), + handleReconnect: requestHandler(RECONNECT_TUNNEL), }; public static location: ISender<ILocation> = { |
