summaryrefslogtreecommitdiffhomepage
path: root/gui/src/renderer
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2019-10-07 14:29:24 +0100
committerEmīls Piņķis <emils@mullvad.net>2019-10-07 14:29:24 +0100
commit49014f53b3ea60a7c37930e2018314f2aac7d1eb (patch)
treed3438a609d90bf63a458804c5ebd90804e1477a2 /gui/src/renderer
parent4a82777ccb2de2bf31b7f464374fc0a5d76b9d4c (diff)
parent1b6abf7a9b59c23725f6fa544c87406f6a2684be (diff)
downloadmullvadvpn-49014f53b3ea60a7c37930e2018314f2aac7d1eb.tar.xz
mullvadvpn-49014f53b3ea60a7c37930e2018314f2aac7d1eb.zip
Merge branch 'gui-login-automatically'
Diffstat (limited to 'gui/src/renderer')
-rw-r--r--gui/src/renderer/app.tsx12
-rw-r--r--gui/src/renderer/components/Account.tsx17
-rw-r--r--gui/src/renderer/components/AppButton.tsx42
-rw-r--r--gui/src/renderer/components/Connect.tsx3
-rw-r--r--gui/src/renderer/components/NotificationArea.tsx4
-rw-r--r--gui/src/renderer/components/NotificationBanner.tsx28
-rw-r--r--gui/src/renderer/components/WireguardKeys.tsx16
-rw-r--r--gui/src/renderer/containers/AccountPage.tsx3
-rw-r--r--gui/src/renderer/containers/ConnectPage.tsx1
-rw-r--r--gui/src/renderer/containers/NotificationAreaContainer.tsx10
-rw-r--r--gui/src/renderer/containers/WireguardKeysPage.tsx3
11 files changed, 98 insertions, 41 deletions
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index f9c2390b25..98ffbc3157 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -3,7 +3,7 @@ import {
push as pushHistory,
replace as replaceHistory,
} from 'connected-react-router';
-import { ipcRenderer, webFrame } from 'electron';
+import { ipcRenderer, shell, webFrame } from 'electron';
import log from 'electron-log';
import { createMemoryHistory } from 'history';
import * as React from 'react';
@@ -288,6 +288,16 @@ export default class AppRenderer {
return IpcRendererEventChannel.accountHistory.removeItem(accountToken);
}
+ public async openLinkWithAuth(link: string): Promise<void> {
+ let token = '';
+ try {
+ token = await IpcRendererEventChannel.account.getWwwAuthToken();
+ } catch (e) {
+ log.error(`Failed to get the WWW auth token: ${e.message}`);
+ }
+ shell.openExternal(`${link}?token=${token}`);
+ }
+
public async setAllowLan(allowLan: boolean) {
const actions = this.reduxActions;
await IpcRendererEventChannel.settings.setAllowLan(allowLan);
diff --git a/gui/src/renderer/components/Account.tsx b/gui/src/renderer/components/Account.tsx
index fb4eb6bf35..1751906026 100644
--- a/gui/src/renderer/components/Account.tsx
+++ b/gui/src/renderer/components/Account.tsx
@@ -18,7 +18,7 @@ interface IProps {
isOffline: boolean;
onLogout: () => void;
onClose: () => void;
- onBuyMore: () => void;
+ onBuyMore: () => Promise<void>;
}
export default class Account extends Component<IProps> {
@@ -65,15 +65,16 @@ export default class Account extends Component<IProps> {
</View>
<View style={styles.account__footer}>
- <AppButton.GreenButton
- style={styles.account__buy_button}
+ <AppButton.BlockingButton
disabled={this.props.isOffline}
onPress={this.props.onBuyMore}>
- <AppButton.Label>
- {messages.pgettext('account-view', 'Buy more credit')}
- </AppButton.Label>
- <AppButton.Icon source="icon-extLink" height={16} width={16} />
- </AppButton.GreenButton>
+ <AppButton.GreenButton style={styles.account__buy_button}>
+ <AppButton.Label>
+ {messages.pgettext('account-view', 'Buy more credit')}
+ </AppButton.Label>
+ <AppButton.Icon source="icon-extLink" height={16} width={16} />
+ </AppButton.GreenButton>
+ </AppButton.BlockingButton>
<AppButton.RedButton onPress={this.props.onLogout}>
{messages.pgettext('account-view', 'Log out')}
</AppButton.RedButton>
diff --git a/gui/src/renderer/components/AppButton.tsx b/gui/src/renderer/components/AppButton.tsx
index 34a7f46e04..6f14fd16e9 100644
--- a/gui/src/renderer/components/AppButton.tsx
+++ b/gui/src/renderer/components/AppButton.tsx
@@ -1,3 +1,4 @@
+import log from 'electron-log';
import * as React from 'react';
import { Button, Component, Styles, Text, Types, UserInterface, View } from 'reactxp';
import { colors } from '../../config.json';
@@ -162,6 +163,47 @@ class BaseButton extends Component<IProps, IState> {
};
}
+interface IBlockingState {
+ isBlocked: boolean;
+}
+
+interface IBlockingProps {
+ children?: React.ReactNode;
+ onPress: () => Promise<void>;
+ disabled?: boolean;
+}
+
+export class BlockingButton extends Component<IBlockingProps, IBlockingState> {
+ public state = {
+ isBlocked: false,
+ };
+
+ public render() {
+ return React.Children.map(this.props.children, (child) => {
+ if (React.isValidElement(child)) {
+ return React.cloneElement(child as React.ReactElement<any>, {
+ ...child.props,
+ disabled: this.state.isBlocked || this.props.disabled,
+ onPress: this.onPress,
+ });
+ } else {
+ return child;
+ }
+ });
+ }
+
+ private onPress = () => {
+ this.setState({ isBlocked: true }, async () => {
+ try {
+ await this.props.onPress();
+ } catch (error) {
+ log.error(`onPress() failed - ${error}`);
+ }
+ this.setState({ isBlocked: false });
+ });
+ };
+}
+
export class RedButton extends BaseButton {
protected backgroundStyle = () => (this.state.hovered ? styles.redHover : styles.red);
}
diff --git a/gui/src/renderer/components/Connect.tsx b/gui/src/renderer/components/Connect.tsx
index d3b9bd0f93..3763751c60 100644
--- a/gui/src/renderer/components/Connect.tsx
+++ b/gui/src/renderer/components/Connect.tsx
@@ -23,7 +23,8 @@ interface IProps {
onSelectLocation: () => void;
onConnect: () => void;
onDisconnect: () => void;
- onExternalLink: (url: string) => void;
+ onExternalLink: (url: string) => Promise<void>;
+ onExternalLinkWithAuth: (url: string) => Promise<void>;
}
type MarkerOrSpinner = 'marker' | 'spinner';
diff --git a/gui/src/renderer/components/NotificationArea.tsx b/gui/src/renderer/components/NotificationArea.tsx
index 01de4f2d83..1d65306ef9 100644
--- a/gui/src/renderer/components/NotificationArea.tsx
+++ b/gui/src/renderer/components/NotificationArea.tsx
@@ -24,8 +24,8 @@ interface IProps {
tunnelState: TunnelState;
version: IVersionReduxState;
blockWhenDisconnected: boolean;
- onOpenDownloadLink: () => void;
- onOpenBuyMoreLink: () => void;
+ onOpenDownloadLink: () => Promise<void>;
+ onOpenBuyMoreLink: () => Promise<void>;
}
type NotificationAreaPresentation =
diff --git a/gui/src/renderer/components/NotificationBanner.tsx b/gui/src/renderer/components/NotificationBanner.tsx
index 56efb41611..b8f935f3c0 100644
--- a/gui/src/renderer/components/NotificationBanner.tsx
+++ b/gui/src/renderer/components/NotificationBanner.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import { Animated, Button, Component, Styles, Text, Types, UserInterface, View } from 'reactxp';
import { colors } from '../../config.json';
+import { BlockingButton } from './AppButton';
import ImageView from './ImageView';
const styles = {
@@ -83,25 +84,26 @@ export class NotificationSubtitle extends Component {
}
}
-export class NotificationOpenLinkAction extends Component<{ onPress: () => void }> {
+export class NotificationOpenLinkAction extends Component<{ onPress: () => Promise<void> }> {
public state = {
hovered: false,
};
public render() {
return (
- <Button
- style={styles.actionButton}
- onPress={this.props.onPress}
- onHoverStart={this.onHoverStart}
- onHoverEnd={this.onHoverEnd}>
- <ImageView
- height={12}
- width={12}
- tintColor={this.state.hovered ? colors.white80 : colors.white60}
- source="icon-extLink"
- />
- </Button>
+ <BlockingButton onPress={this.props.onPress}>
+ <Button
+ style={styles.actionButton}
+ onHoverStart={this.onHoverStart}
+ onHoverEnd={this.onHoverEnd}>
+ <ImageView
+ height={12}
+ width={12}
+ tintColor={this.state.hovered ? colors.white80 : colors.white60}
+ source="icon-extLink"
+ />
+ </Button>
+ </BlockingButton>
);
}
diff --git a/gui/src/renderer/components/WireguardKeys.tsx b/gui/src/renderer/components/WireguardKeys.tsx
index 966d751b4f..9a65fe92e9 100644
--- a/gui/src/renderer/components/WireguardKeys.tsx
+++ b/gui/src/renderer/components/WireguardKeys.tsx
@@ -21,7 +21,7 @@ export interface IProps {
onGenerateKey: () => void;
onReplaceKey: (old: IWgKey) => void;
onVerifyKey: (publicKey: IWgKey) => void;
- onVisitWebsiteKey: () => void;
+ onVisitWebsiteKey: () => Promise<void>;
}
export default class WireguardKeys extends Component<IProps> {
@@ -85,14 +85,16 @@ export default class WireguardKeys extends Component<IProps> {
</AppButton.GreenButton>
</View>
<View style={styles.wgkeys__row}>
- <AppButton.GreenButton
+ <AppButton.BlockingButton
disabled={this.props.isOffline}
onPress={this.props.onVisitWebsiteKey}>
- <AppButton.Label>
- {messages.pgettext('wireguard-key-view', 'Manage keys')}
- </AppButton.Label>
- <AppButton.Icon source="icon-extLink" height={16} width={16} />
- </AppButton.GreenButton>
+ <AppButton.GreenButton>
+ <AppButton.Label>
+ {messages.pgettext('wireguard-key-view', 'Manage keys')}
+ </AppButton.Label>
+ <AppButton.Icon source="icon-extLink" height={16} width={16} />
+ </AppButton.GreenButton>
+ </AppButton.BlockingButton>
</View>
</View>
</View>
diff --git a/gui/src/renderer/containers/AccountPage.tsx b/gui/src/renderer/containers/AccountPage.tsx
index 4880cec68e..0fea11da8b 100644
--- a/gui/src/renderer/containers/AccountPage.tsx
+++ b/gui/src/renderer/containers/AccountPage.tsx
@@ -1,5 +1,4 @@
import { goBack } from 'connected-react-router';
-import { shell } from 'electron';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { links } from '../../config.json';
@@ -23,7 +22,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => {
onClose: () => {
history.goBack();
},
- onBuyMore: () => shell.openExternal(links.purchase),
+ onBuyMore: () => props.app.openLinkWithAuth(links.purchase),
};
};
diff --git a/gui/src/renderer/containers/ConnectPage.tsx b/gui/src/renderer/containers/ConnectPage.tsx
index 8d30bdc149..b473a523c8 100644
--- a/gui/src/renderer/containers/ConnectPage.tsx
+++ b/gui/src/renderer/containers/ConnectPage.tsx
@@ -101,6 +101,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => {
}
},
onExternalLink: (url: string) => shell.openExternal(url),
+ onExternalLinkWithAuth: (url: string) => props.app.openLinkWithAuth(url),
};
};
diff --git a/gui/src/renderer/containers/NotificationAreaContainer.tsx b/gui/src/renderer/containers/NotificationAreaContainer.tsx
index 90c8938b9d..814b055d97 100644
--- a/gui/src/renderer/containers/NotificationAreaContainer.tsx
+++ b/gui/src/renderer/containers/NotificationAreaContainer.tsx
@@ -16,13 +16,13 @@ const mapStateToProps = (state: IReduxState, _props: IAppContext) => ({
blockWhenDisconnected: state.settings.blockWhenDisconnected,
});
-const mapDispatchToProps = (_dispatch: ReduxDispatch, _props: IAppContext) => {
+const mapDispatchToProps = (_dispatch: ReduxDispatch, props: IAppContext) => {
return {
- onOpenDownloadLink() {
- shell.openExternal(links.download);
+ onOpenDownloadLink(): Promise<void> {
+ return shell.openExternal(links.download);
},
- onOpenBuyMoreLink() {
- shell.openExternal(links.purchase);
+ onOpenBuyMoreLink(): Promise<void> {
+ return props.app.openLinkWithAuth(links.purchase);
},
};
};
diff --git a/gui/src/renderer/containers/WireguardKeysPage.tsx b/gui/src/renderer/containers/WireguardKeysPage.tsx
index 911093f9ca..9f5a4aa8d2 100644
--- a/gui/src/renderer/containers/WireguardKeysPage.tsx
+++ b/gui/src/renderer/containers/WireguardKeysPage.tsx
@@ -1,5 +1,4 @@
import { goBack, push } from 'connected-react-router';
-import { shell } from 'electron';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { links } from '../../config.json';
@@ -20,7 +19,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => {
onGenerateKey: () => props.app.generateWireguardKey(),
onReplaceKey: (oldKey: IWgKey) => props.app.replaceWireguardKey(oldKey),
onVerifyKey: (publicKey: IWgKey) => props.app.verifyWireguardKey(publicKey),
- onVisitWebsiteKey: () => shell.openExternal(links.manageKeys),
+ onVisitWebsiteKey: () => props.app.openLinkWithAuth(links.manageKeys),
};
};