summaryrefslogtreecommitdiffhomepage
path: root/gui
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2020-05-19 12:07:03 +0200
committerOskar Nyberg <oskar@mullvad.net>2020-05-19 12:07:03 +0200
commit17a1b03fb8a21844c815d0b8f4efea3a26526064 (patch)
tree6ccbdd334b127e135857b65d8802a0e40d77d690 /gui
parent5d3f86a2cfc78c5014dceacba4f0011e7ed7875f (diff)
parent2fe210f325d53cc64fd2742976a93aa0816b1ebb (diff)
downloadmullvadvpn-17a1b03fb8a21844c815d0b8f4efea3a26526064.tar.xz
mullvadvpn-17a1b03fb8a21844c815d0b8f4efea3a26526064.zip
Merge branch 'add-voucher-payment-to-account-view'
Diffstat (limited to 'gui')
-rw-r--r--gui/src/renderer/components/Account.tsx103
-rw-r--r--gui/src/renderer/components/AccountStyles.tsx2
-rw-r--r--gui/src/renderer/components/ExpiredAccountErrorView.tsx39
-rw-r--r--gui/src/renderer/components/RedeemVoucher.tsx52
-rw-r--r--gui/src/renderer/components/RedeemVoucherStyles.tsx9
5 files changed, 120 insertions, 85 deletions
diff --git a/gui/src/renderer/components/Account.tsx b/gui/src/renderer/components/Account.tsx
index 0055a32049..7863040f83 100644
--- a/gui/src/renderer/components/Account.tsx
+++ b/gui/src/renderer/components/Account.tsx
@@ -13,7 +13,9 @@ import styles, {
import AccountTokenLabel from './AccountTokenLabel';
import * as AppButton from './AppButton';
import { Layout } from './Layout';
+import { ModalContainer } from './Modal';
import { BackBarItem, NavigationBar, NavigationItems } from './NavigationBar';
+import { RedeemVoucherButton } from './RedeemVoucher';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
import { AccountToken } from '../../shared/daemon-rpc-types';
@@ -31,58 +33,63 @@ interface IProps {
export default class Account extends React.Component<IProps> {
public render() {
return (
- <Layout>
- <StyledContainer>
- <NavigationBar>
- <NavigationItems>
- <BackBarItem action={this.props.onClose}>
- {
- // TRANSLATORS: Back button in navigation bar
- messages.pgettext('navigation-bar', 'Settings')
- }
- </BackBarItem>
- </NavigationItems>
- </NavigationBar>
+ <ModalContainer>
+ <Layout>
+ <StyledContainer>
+ <NavigationBar>
+ <NavigationItems>
+ <BackBarItem action={this.props.onClose}>
+ {
+ // TRANSLATORS: Back button in navigation bar
+ messages.pgettext('navigation-bar', 'Settings')
+ }
+ </BackBarItem>
+ </NavigationItems>
+ </NavigationBar>
- <AccountContainer>
- <SettingsHeader>
- <HeaderTitle>{messages.pgettext('account-view', 'Account')}</HeaderTitle>
- </SettingsHeader>
+ <AccountContainer>
+ <SettingsHeader>
+ <HeaderTitle>{messages.pgettext('account-view', 'Account')}</HeaderTitle>
+ </SettingsHeader>
- <AccountRow>
- <AccountRowLabel>
- {messages.pgettext('account-view', 'Account number')}
- </AccountRowLabel>
- <AccountRowValue
- as={AccountTokenLabel}
- accountToken={this.props.accountToken || ''}
- />
- </AccountRow>
+ <AccountRow>
+ <AccountRowLabel>
+ {messages.pgettext('account-view', 'Account number')}
+ </AccountRowLabel>
+ <AccountRowValue
+ as={AccountTokenLabel}
+ accountToken={this.props.accountToken || ''}
+ />
+ </AccountRow>
- <AccountRow>
- <AccountRowLabel>{messages.pgettext('account-view', 'Paid until')}</AccountRowLabel>
- <FormattedAccountExpiry
- expiry={this.props.accountExpiry}
- locale={this.props.expiryLocale}
- />
- </AccountRow>
+ <AccountRow>
+ <AccountRowLabel>{messages.pgettext('account-view', 'Paid until')}</AccountRowLabel>
+ <FormattedAccountExpiry
+ expiry={this.props.accountExpiry}
+ locale={this.props.expiryLocale}
+ />
+ </AccountRow>
- <AccountFooter>
- <AppButton.BlockingButton
- disabled={this.props.isOffline}
- onPress={this.props.onBuyMore}>
- <AppButton.GreenButton style={styles.account__buy_button}>
- <AppButton.Label>{messages.gettext('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>
- </AccountFooter>
- </AccountContainer>
- </StyledContainer>
- </Layout>
+ <AccountFooter>
+ <AppButton.BlockingButton
+ disabled={this.props.isOffline}
+ onPress={this.props.onBuyMore}>
+ <AppButton.GreenButton style={styles.button}>
+ <AppButton.Label>{messages.gettext('Buy more credit')}</AppButton.Label>
+ <AppButton.Icon source="icon-extLink" height={16} width={16} />
+ </AppButton.GreenButton>
+ </AppButton.BlockingButton>
+
+ <RedeemVoucherButton style={styles.button} />
+
+ <AppButton.RedButton onPress={this.props.onLogout}>
+ {messages.pgettext('account-view', 'Log out')}
+ </AppButton.RedButton>
+ </AccountFooter>
+ </AccountContainer>
+ </StyledContainer>
+ </Layout>
+ </ModalContainer>
);
}
}
diff --git a/gui/src/renderer/components/AccountStyles.tsx b/gui/src/renderer/components/AccountStyles.tsx
index c793b96a1b..970309e4f8 100644
--- a/gui/src/renderer/components/AccountStyles.tsx
+++ b/gui/src/renderer/components/AccountStyles.tsx
@@ -52,7 +52,7 @@ export const AccountFooter = styled.div({
});
export default {
- account__buy_button: Styles.createViewStyle({
+ button: Styles.createViewStyle({
marginBottom: 24,
}),
};
diff --git a/gui/src/renderer/components/ExpiredAccountErrorView.tsx b/gui/src/renderer/components/ExpiredAccountErrorView.tsx
index 5703a33947..51c1867cf9 100644
--- a/gui/src/renderer/components/ExpiredAccountErrorView.tsx
+++ b/gui/src/renderer/components/ExpiredAccountErrorView.tsx
@@ -5,7 +5,6 @@ import { links } from '../../config.json';
import AccountExpiry from '../../shared/account-expiry';
import { AccountToken } from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
-import { RedeemVoucherContainer } from '../components/RedeemVoucher';
import { LoginState } from '../redux/account/reducers';
import * as AppButton from './AppButton';
import * as Cell from './Cell';
@@ -13,11 +12,7 @@ import CustomScrollbars from './CustomScrollbars';
import styles, { StyledAccountTokenLabel } from './ExpiredAccountErrorViewStyles';
import ImageView from './ImageView';
import { ModalAlert, ModalAlertType } from './Modal';
-import {
- RedeemVoucherInput,
- RedeemVoucherResponse,
- RedeemVoucherSubmitButton,
-} from './RedeemVoucher';
+import { RedeemVoucherContainer, RedeemVoucherAlert } from './RedeemVoucher';
export enum RecoveryAction {
openBrowser,
@@ -40,7 +35,6 @@ interface IExpiredAccountErrorViewProps {
interface IExpiredAccountErrorViewState {
showBlockWhenDisconnectedAlert: boolean;
showRedeemVoucherAlert: boolean;
- redeemingVoucher: boolean;
}
export default class ExpiredAccountErrorView extends Component<
@@ -50,7 +44,6 @@ export default class ExpiredAccountErrorView extends Component<
public state: IExpiredAccountErrorViewState = {
showBlockWhenDisconnectedAlert: false,
showRedeemVoucherAlert: false,
- redeemingVoucher: false,
};
public componentDidUpdate() {
@@ -175,26 +168,8 @@ export default class ExpiredAccountErrorView extends Component<
private renderRedeemVoucherAlert() {
return (
- <RedeemVoucherContainer
- onSubmit={this.onVoucherSubmit}
- onSuccess={this.props.hideWelcomeView}
- onFailure={this.onVoucherResponse}>
- <ModalAlert
- buttons={[
- <RedeemVoucherSubmitButton key="submit" />,
- <AppButton.BlueButton
- key="cancel"
- disabled={this.state.redeemingVoucher}
- onPress={this.onCloseRedeemVoucherAlert}>
- {messages.gettext('Cancel')}
- </AppButton.BlueButton>,
- ]}>
- <Text style={styles.fieldLabel}>
- {messages.pgettext('connect-view', 'Enter voucher code')}
- </Text>
- <RedeemVoucherInput />
- <RedeemVoucherResponse />
- </ModalAlert>
+ <RedeemVoucherContainer onSuccess={this.props.hideWelcomeView}>
+ <RedeemVoucherAlert onClose={this.onCloseRedeemVoucherAlert} />
</RedeemVoucherContainer>
);
}
@@ -269,14 +244,6 @@ export default class ExpiredAccountErrorView extends Component<
this.setState({ showRedeemVoucherAlert: false });
};
- private onVoucherSubmit = () => {
- this.setState({ redeemingVoucher: true });
- };
-
- private onVoucherResponse = () => {
- this.setState({ redeemingVoucher: false });
- };
-
private onCloseBlockWhenDisconnectedInstructions = () => {
this.setState({ showBlockWhenDisconnectedAlert: false });
};
diff --git a/gui/src/renderer/components/RedeemVoucher.tsx b/gui/src/renderer/components/RedeemVoucher.tsx
index 39f3e68d3d..ad16523f54 100644
--- a/gui/src/renderer/components/RedeemVoucher.tsx
+++ b/gui/src/renderer/components/RedeemVoucher.tsx
@@ -1,14 +1,19 @@
import React, { useCallback, useContext, useState } from 'react';
+import { useSelector } from 'react-redux';
+import { Types } from 'reactxp';
import { VoucherResponse } from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
import { useAppContext } from '../context';
import useActions from '../lib/actionsHook';
import accountActions from '../redux/account/actions';
+import { IReduxState } from '../redux/store';
import * as AppButton from './AppButton';
+import { ModalAlert } from './Modal';
import {
StyledEmptyResponse,
StyledErrorResponse,
StyledInput,
+ StyledLabel,
StyledSpinner,
StyledSuccessResponse,
} from './RedeemVoucherStyles';
@@ -171,3 +176,50 @@ export function RedeemVoucherSubmitButton() {
</AppButton.GreenButton>
);
}
+
+interface IRedeemVoucherAlertProps {
+ onClose?: () => void;
+}
+
+export function RedeemVoucherAlert(props: IRedeemVoucherAlertProps) {
+ const { submitting } = useContext(RedeemVoucherContext);
+
+ return (
+ <ModalAlert
+ buttons={[
+ <RedeemVoucherSubmitButton key="submit" />,
+ <AppButton.BlueButton key="cancel" disabled={submitting} onPress={props.onClose}>
+ {messages.pgettext('redeem-voucher-alert', 'Cancel')}
+ </AppButton.BlueButton>,
+ ]}>
+ <StyledLabel>{messages.pgettext('redeem-voucher-alert', 'Enter voucher code')}</StyledLabel>
+ <RedeemVoucherInput />
+ <RedeemVoucherResponse />
+ </ModalAlert>
+ );
+}
+
+interface IRedeemVoucherButtonProps {
+ style?: Types.StyleRuleSetRecursive<Types.ViewStyleRuleSet>;
+}
+
+export function RedeemVoucherButton(props: IRedeemVoucherButtonProps) {
+ const isBlocked = useSelector((state: IReduxState) => state.connection.isBlocked);
+ const [showAlert, setShowAlert] = useState(false);
+
+ const onPress = useCallback(() => setShowAlert(true), []);
+ const onAlertClose = useCallback(() => setShowAlert(false), []);
+
+ return (
+ <>
+ <AppButton.GreenButton disabled={isBlocked} onPress={onPress} style={props.style}>
+ {messages.pgettext('redeem-voucher-alert', 'Redeem voucher')}
+ </AppButton.GreenButton>
+ {showAlert && (
+ <RedeemVoucherContainer onSuccess={onAlertClose}>
+ <RedeemVoucherAlert onClose={onAlertClose} />
+ </RedeemVoucherContainer>
+ )}
+ </>
+ );
+}
diff --git a/gui/src/renderer/components/RedeemVoucherStyles.tsx b/gui/src/renderer/components/RedeemVoucherStyles.tsx
index 6ce463fab9..cd7d0cc7eb 100644
--- a/gui/src/renderer/components/RedeemVoucherStyles.tsx
+++ b/gui/src/renderer/components/RedeemVoucherStyles.tsx
@@ -2,6 +2,15 @@ import styled from 'styled-components';
import { colors } from '../../config.json';
import ImageView from './ImageView';
+export const StyledLabel = styled.span({
+ fontFamily: 'Open Sans',
+ fontSize: '13px',
+ fontWeight: 600,
+ lineHeight: '20px',
+ color: colors.white,
+ marginBottom: '9px',
+});
+
export const StyledInput = styled.input({
flex: 1,
overflow: 'hidden',