summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2021-06-28 12:48:21 +0200
committerOskar Nyberg <oskar@mullvad.net>2021-06-28 12:48:21 +0200
commit3731b548ff7c3aa2d8fe2a48f4e4626f5f87c92f (patch)
treeb8402e747fde056460e4c2384c83de40bf4df4ae
parent4d95c0a019c2d7bfb2c3ca4951febfded93e9758 (diff)
parent2c718e73f1df2fa0452bf0fef482cf4692d5020b (diff)
downloadmullvadvpn-3731b548ff7c3aa2d8fe2a48f4e4626f5f87c92f.tar.xz
mullvadvpn-3731b548ff7c3aa2d8fe2a48f4e4626f5f87c92f.zip
Merge branch 'redesigned-voucher-dialog'
-rw-r--r--gui/locales/messages.pot45
-rw-r--r--gui/src/renderer/components/ExpiredAccountAddTime.tsx7
-rw-r--r--gui/src/renderer/components/RedeemVoucher.tsx99
-rw-r--r--gui/src/renderer/components/RedeemVoucherStyles.tsx33
4 files changed, 142 insertions, 42 deletions
diff --git a/gui/locales/messages.pot b/gui/locales/messages.pot
index ab24bf500c..0ea0b1c0fd 100644
--- a/gui/locales/messages.pot
+++ b/gui/locales/messages.pot
@@ -2,6 +2,9 @@ msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
+msgid "%(duration)s was added to your account."
+msgstr ""
+
msgid "1 day"
msgid_plural "%d days"
msgstr[0] ""
@@ -93,6 +96,9 @@ msgstr ""
msgid "FAILED TO SECURE CONNECTION"
msgstr ""
+msgid "Got it!"
+msgstr ""
+
msgid "Invalid account number"
msgstr ""
@@ -105,6 +111,9 @@ msgstr ""
msgid "less than a minute ago"
msgstr ""
+msgid "Next"
+msgstr ""
+
msgid "Open URL"
msgstr ""
@@ -385,10 +394,22 @@ msgid "Either buy credit on our website or redeem a voucher."
msgstr ""
msgctxt "connect-view"
+msgid "Enter voucher code"
+msgstr ""
+
+msgctxt "connect-view"
+msgid "Go ahead and start using the app to begin reclaiming your online privacy."
+msgstr ""
+
+msgctxt "connect-view"
msgid "Here’s your account number. Save it!"
msgstr ""
msgctxt "connect-view"
+msgid "Learn about privacy"
+msgstr ""
+
+msgctxt "connect-view"
msgid "Out of time"
msgstr ""
@@ -401,14 +422,30 @@ msgid "Remember, turning it off will allow network traffic while the VPN is disc
msgstr ""
msgctxt "connect-view"
+msgid "Start using the app"
+msgstr ""
+
+msgctxt "connect-view"
+msgid "Time was successfully added"
+msgstr ""
+
+msgctxt "connect-view"
msgid "To add more, you will need to disconnect and access the Internet with an unsecure connection."
msgstr ""
msgctxt "connect-view"
+msgid "To continue your journey as a privacy ninja, visit our website to pick up other privacy-friendly habits and tools."
+msgstr ""
+
+msgctxt "connect-view"
msgid "To start using the app, you first need to add time to your account."
msgstr ""
msgctxt "connect-view"
+msgid "Voucher was successfully redeemed"
+msgstr ""
+
+msgctxt "connect-view"
msgid "You have no more VPN time left on this account."
msgstr ""
@@ -416,6 +453,10 @@ msgctxt "connect-view"
msgid "You need to disable \"Always require VPN\" in order to access the Internet to add time."
msgstr ""
+msgctxt "connect-view"
+msgid "You're all set!"
+msgstr ""
+
#. The hostname line displayed below the country on the main screen
#. Available placeholders:
#. %(relay)s - the relay hostname
@@ -814,6 +855,10 @@ msgid "Redeem"
msgstr ""
msgctxt "redeem-voucher-view"
+msgid "Verifying voucher..."
+msgstr ""
+
+msgctxt "redeem-voucher-view"
msgid "Voucher code has already been used."
msgstr ""
diff --git a/gui/src/renderer/components/ExpiredAccountAddTime.tsx b/gui/src/renderer/components/ExpiredAccountAddTime.tsx
index 9831430d4e..a9b83af6a6 100644
--- a/gui/src/renderer/components/ExpiredAccountAddTime.tsx
+++ b/gui/src/renderer/components/ExpiredAccountAddTime.tsx
@@ -100,7 +100,7 @@ export function VoucherInput() {
<StyledTitle>{messages.pgettext('connect-view', 'Redeem voucher')}</StyledTitle>
<StyledLabel>{messages.pgettext('connect-view', 'Enter voucher code')}</StyledLabel>
<StyledRedeemVoucherInput />
- <RedeemVoucherResponse disableSuccessMessage />
+ <RedeemVoucherResponse />
</StyledBody>
<StyledFooter>
@@ -164,10 +164,7 @@ export function TimeAdded(props: ITimeAddedProps) {
{props.title ?? messages.pgettext('connect-view', 'Time was successfully added')}
</StyledTitle>
<StyledLabel>
- {sprintf(
- messages.pgettext('connect-view', '%(duration)s was added to your account.'),
- { duration },
- )}
+ {sprintf(messages.gettext('%(duration)s was added to your account.'), { duration })}
</StyledLabel>
</StyledBody>
diff --git a/gui/src/renderer/components/RedeemVoucher.tsx b/gui/src/renderer/components/RedeemVoucher.tsx
index b878a94c4f..c7697f2f6f 100644
--- a/gui/src/renderer/components/RedeemVoucher.tsx
+++ b/gui/src/renderer/components/RedeemVoucher.tsx
@@ -1,18 +1,26 @@
import React, { useCallback, useContext, useState } from 'react';
+import { useSelector } from 'react-redux';
+import { sprintf } from 'sprintf-js';
import { VoucherResponse } from '../../shared/daemon-rpc-types';
+import { formatRelativeDate } from '../../shared/date-helper';
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 ImageView from './ImageView';
import { ModalAlert } from './Modal';
import {
StyledEmptyResponse,
StyledErrorResponse,
StyledInput,
StyledLabel,
+ StyledProgressResponse,
+ StyledProgressWrapper,
StyledSpinner,
- StyledSuccessResponse,
+ StyledStatusIcon,
+ StyledTitle,
} from './RedeemVoucherStyles';
const MIN_VOUCHER_LENGTH = 16;
@@ -143,29 +151,26 @@ export function RedeemVoucherInput(props: IRedeemVoucherInputProps) {
);
}
-interface IRedeemVoucherResponseProps {
- disableSuccessMessage?: boolean;
-}
-
-export function RedeemVoucherResponse(props: IRedeemVoucherResponseProps) {
+export function RedeemVoucherResponse() {
const { response, submitting } = useContext(RedeemVoucherContext);
if (submitting) {
- return <StyledSpinner source="icon-spinner" height={20} width={20} />;
+ return (
+ <>
+ <StyledProgressWrapper>
+ <StyledSpinner source="icon-spinner" height={20} width={20} />
+ <StyledProgressResponse>
+ {messages.pgettext('redeem-voucher-view', 'Verifying voucher...')}
+ </StyledProgressResponse>
+ </StyledProgressWrapper>
+ </>
+ );
}
if (response) {
switch (response.type) {
case 'success':
- if (props.disableSuccessMessage) {
- return <StyledEmptyResponse />;
- } else {
- return (
- <StyledSuccessResponse>
- {messages.pgettext('redeem-voucher-view', 'Voucher was successfully redeemed.')}
- </StyledSuccessResponse>
- );
- }
+ return <StyledEmptyResponse />;
case 'invalid':
return (
<StyledErrorResponse>
@@ -207,22 +212,52 @@ interface IRedeemVoucherAlertProps {
export function RedeemVoucherAlert(props: IRedeemVoucherAlertProps) {
const { submitting, response } = useContext(RedeemVoucherContext);
- const cancelDisabled = submitting || response?.type === 'success';
+ const accountData = useSelector((state: IReduxState) => state.account);
- return (
- <ModalAlert
- buttons={[
- <RedeemVoucherSubmitButton key="submit" />,
- <AppButton.BlueButton key="cancel" disabled={cancelDisabled} onClick={props.onClose}>
- {messages.pgettext('redeem-voucher-alert', 'Cancel')}
- </AppButton.BlueButton>,
- ]}
- close={props.onClose}>
- <StyledLabel>{messages.pgettext('redeem-voucher-alert', 'Enter voucher code')}</StyledLabel>
- <RedeemVoucherInput />
- <RedeemVoucherResponse />
- </ModalAlert>
- );
+ const duration =
+ (accountData.expiry &&
+ accountData.previousExpiry &&
+ formatRelativeDate(accountData.expiry, accountData.previousExpiry)) ??
+ '';
+
+ if (response?.type === 'success') {
+ return (
+ <ModalAlert
+ buttons={[
+ <AppButton.BlueButton key="gotit" onClick={props.onClose}>
+ {messages.gettext('Got it!')}
+ </AppButton.BlueButton>,
+ ]}
+ close={props.onClose}>
+ <StyledStatusIcon>
+ <ImageView source="icon-success" height={60} width={60} />
+ </StyledStatusIcon>
+ <StyledTitle>
+ {messages.pgettext('redeem-voucher-view', 'Voucher was successfully redeemed.')}
+ </StyledTitle>
+ <StyledLabel>
+ {sprintf(messages.gettext('%(duration)s was added to your account.'), {
+ duration,
+ })}
+ </StyledLabel>
+ </ModalAlert>
+ );
+ } else {
+ return (
+ <ModalAlert
+ buttons={[
+ <RedeemVoucherSubmitButton key="submit" />,
+ <AppButton.BlueButton key="cancel" disabled={submitting} onClick={props.onClose}>
+ {messages.pgettext('redeem-voucher-alert', 'Cancel')}
+ </AppButton.BlueButton>,
+ ]}
+ close={props.onClose}>
+ <StyledLabel>{messages.pgettext('redeem-voucher-alert', 'Enter voucher code')}</StyledLabel>
+ <RedeemVoucherInput />
+ <RedeemVoucherResponse />
+ </ModalAlert>
+ );
+ }
}
interface IRedeemVoucherButtonProps {
@@ -241,7 +276,7 @@ export function RedeemVoucherButton(props: IRedeemVoucherButtonProps) {
{messages.pgettext('redeem-voucher-alert', 'Redeem voucher')}
</AppButton.GreenButton>
{showAlert && (
- <RedeemVoucherContainer onSuccess={onClose}>
+ <RedeemVoucherContainer>
<RedeemVoucherAlert onClose={onClose} />
</RedeemVoucherContainer>
)}
diff --git a/gui/src/renderer/components/RedeemVoucherStyles.tsx b/gui/src/renderer/components/RedeemVoucherStyles.tsx
index e710bfe5bf..bbf20067b3 100644
--- a/gui/src/renderer/components/RedeemVoucherStyles.tsx
+++ b/gui/src/renderer/components/RedeemVoucherStyles.tsx
@@ -34,15 +34,21 @@ export const StyledResponse = styled.span({
fontFamily: 'Open Sans',
fontSize: '13px',
lineHeight: '20px',
+ fontWeight: 800,
+ color: colors.white,
});
-export const StyledSuccessResponse = styled(StyledResponse)({
- fontWeight: 600,
- color: colors.green,
+export const StyledProgressWrapper = styled.div({
+ display: 'flex',
+ alignItems: 'center',
+ marginTop: '8px',
+});
+
+export const StyledProgressResponse = styled(StyledResponse)({
+ marginTop: 0,
});
export const StyledErrorResponse = styled(StyledResponse)({
- fontWeight: 800,
color: colors.red,
});
@@ -52,5 +58,22 @@ export const StyledEmptyResponse = styled.span({
});
export const StyledSpinner = styled(ImageView)({
- marginTop: '8px',
+ marginRight: '8px',
+});
+
+export const StyledStatusIcon = styled.div({
+ alignSelf: 'center',
+ width: '60px',
+ height: '60px',
+ marginBottom: '18px',
+ marginTop: '25px',
+});
+
+export const StyledTitle = styled.span({
+ fontFamily: 'Open Sans',
+ fontSize: '16px',
+ lineHeight: '22px',
+ fontWeight: 800,
+ color: colors.white,
+ marginBottom: '5px',
});