diff options
| -rw-r--r-- | gui/locales/messages.pot | 45 | ||||
| -rw-r--r-- | gui/src/renderer/components/ExpiredAccountAddTime.tsx | 7 | ||||
| -rw-r--r-- | gui/src/renderer/components/RedeemVoucher.tsx | 99 | ||||
| -rw-r--r-- | gui/src/renderer/components/RedeemVoucherStyles.tsx | 33 |
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', }); |
