diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-02-07 18:08:18 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-02-09 12:51:56 +0100 |
| commit | 4998b06e1516b1724ae0dc08576a553772b92565 (patch) | |
| tree | e0b43819a7d9d67d416e580c8450facc3b24e451 /gui/src | |
| parent | bfd238f74448195f3d515dd2045678a2e9b7821a (diff) | |
| download | mullvadvpn-4998b06e1516b1724ae0dc08576a553772b92565.tar.xz mullvadvpn-4998b06e1516b1724ae0dc08576a553772b92565.zip | |
Show correct time added information
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/renderer/components/ExpiredAccountAddTime.tsx | 59 | ||||
| -rw-r--r-- | gui/src/renderer/lib/history.tsx | 28 | ||||
| -rw-r--r-- | gui/src/renderer/lib/routes.ts | 13 |
3 files changed, 68 insertions, 32 deletions
diff --git a/gui/src/renderer/components/ExpiredAccountAddTime.tsx b/gui/src/renderer/components/ExpiredAccountAddTime.tsx index 49e8bf8107..4c6c7989d7 100644 --- a/gui/src/renderer/components/ExpiredAccountAddTime.tsx +++ b/gui/src/renderer/components/ExpiredAccountAddTime.tsx @@ -1,16 +1,16 @@ import { useCallback } from 'react'; -import { useSelector } from 'react-redux'; +import { useSelector } from '../redux/store'; import { sprintf } from 'sprintf-js'; import styled from 'styled-components'; import { links, colors } from '../../config.json'; +import { formatDate } from '../../shared/account-expiry'; import { formatRelativeDate } from '../../shared/date-helper'; import { messages } from '../../shared/gettext'; import { useAppContext } from '../context'; import useActions from '../lib/actionsHook'; import { transitions, useHistory } from '../lib/history'; -import { RoutePath } from '../lib/routes'; +import { generateRoutePath, RoutePath } from '../lib/routes'; import account from '../redux/account/actions'; -import { IReduxState } from '../redux/store'; import * as AppButton from './AppButton'; import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGroup'; import { bigText } from './common-styles'; @@ -24,6 +24,7 @@ import { RedeemVoucherResponse, RedeemVoucherSubmitButton, } from './RedeemVoucher'; +import { useParams } from 'react-router'; export const StyledHeader = styled(DefaultHeaderBar)({ flex: 0, @@ -82,9 +83,13 @@ export const StyledStatusIcon = styled.div({ export function VoucherInput() { const history = useHistory(); - const onSuccess = useCallback(() => { - history.push(RoutePath.voucherSuccess); - }, [history]); + const onSuccess = useCallback( + (newExpiry: string, secondsAdded: number) => { + const path = generateRoutePath(RoutePath.voucherSuccess, { newExpiry, secondsAdded }); + history.push(path); + }, + [history], + ); const navigateBack = useCallback(() => { history.pop(); @@ -119,23 +124,31 @@ export function VoucherInput() { } export function VoucherVerificationSuccess() { + const { newExpiry, secondsAdded } = useParams<{ newExpiry: string; secondsAdded: string }>(); + return ( - <TimeAdded title={messages.pgettext('connect-view', 'Voucher was successfully redeemed')} /> + <TimeAdded + newExpiry={newExpiry} + secondsAdded={parseInt(secondsAdded)} + title={messages.pgettext('connect-view', 'Voucher was successfully redeemed')} + /> ); } interface ITimeAddedProps { title?: string; + newExpiry?: string; + secondsAdded?: number; } export function TimeAdded(props: ITimeAddedProps) { const history = useHistory(); const finish = useFinishedCallback(); - const accountData = useSelector((state: IReduxState) => state.account); + const expiry = useSelector((state) => state.account.expiry); const isNewAccount = useSelector( - (state: IReduxState) => - state.account.status.type === 'ok' && state.account.status.method === 'new_account', + (state) => state.account.status.type === 'ok' && state.account.status.method === 'new_account', ); + const locale = useSelector((state) => state.userInterface.locale); const navigateToSetupFinished = useCallback(() => { if (isNewAccount) { @@ -146,10 +159,8 @@ export function TimeAdded(props: ITimeAddedProps) { }, [history, finish]); const duration = - (accountData.expiry && - accountData.previousExpiry && - formatRelativeDate(accountData.expiry, accountData.previousExpiry)) ?? - ''; + props.secondsAdded !== undefined ? formatRelativeDate(props.secondsAdded * 1000, 0) : undefined; + const newExpiry = formatDate(props.newExpiry ?? expiry!, locale); return ( <Layout> @@ -164,7 +175,17 @@ export function TimeAdded(props: ITimeAddedProps) { {props.title ?? messages.pgettext('connect-view', 'Time was successfully added')} </StyledTitle> <StyledLabel> - {sprintf(messages.gettext('%(duration)s was added to your account.'), { duration })} + {duration + ? sprintf( + messages.gettext('%(duration)s was added, account paid until %(expiry)s.'), + { + duration, + expiry: newExpiry, + }, + ) + : sprintf(messages.gettext('Account paid until %(expiry)s.'), { + expiry: newExpiry, + })} </StyledLabel> </StyledBody> @@ -238,10 +259,9 @@ export function SetupFinished() { function HeaderBar() { const isNewAccount = useSelector( - (state: IReduxState) => - state.account.status.type === 'ok' && state.account.status.method === 'new_account', + (state) => state.account.status.type === 'ok' && state.account.status.method === 'new_account', ); - const tunnelState = useSelector((state: IReduxState) => state.connection.status); + const tunnelState = useSelector((state) => state.connection.status); const headerBarStyle = isNewAccount ? HeaderBarStyle.default : calculateHeaderBarStyle(tunnelState); @@ -254,8 +274,7 @@ function useFinishedCallback() { const history = useHistory(); const isNewAccount = useSelector( - (state: IReduxState) => - state.account.status.type === 'ok' && state.account.status.method === 'new_account', + (state) => state.account.status.type === 'ok' && state.account.status.method === 'new_account', ); const callback = useCallback(() => { diff --git a/gui/src/renderer/lib/history.tsx b/gui/src/renderer/lib/history.tsx index 4abdcd5fcb..f5bc213112 100644 --- a/gui/src/renderer/lib/history.tsx +++ b/gui/src/renderer/lib/history.tsx @@ -1,7 +1,7 @@ import { Location, Action, LocationDescriptorObject, History as OriginalHistory } from 'history'; import React from 'react'; import { RouteComponentProps, useHistory as useReactRouterHistory, withRouter } from 'react-router'; -import { RoutePath } from './routes'; +import { GeneratedRoutePath, RoutePath } from './routes'; export interface ITransitionSpecification { name: string; @@ -38,7 +38,7 @@ export const transitions: ITransitionMap = { }, }; -type LocationDescriptor<S> = RoutePath | LocationDescriptorObject<S>; +type LocationDescriptor<S> = RoutePath | GeneratedRoutePath | LocationDescriptorObject<S>; type LocationListener<S = unknown> = ( location: Location<S>, @@ -168,7 +168,11 @@ export default class History { } private createLocation(location: LocationDescriptor<S>, state?: S): Location<S> { - if (typeof location === 'object') { + if (typeof location === 'string') { + return this.createLocationFromString(location, state); + } else if ('routePath' in location) { + return this.createLocationFromString(location.routePath, state); + } else { return { pathname: location.pathname ?? this.location.pathname, search: location.search ?? '', @@ -176,17 +180,19 @@ export default class History { state: location.state, key: location.key ?? this.getRandomKey(), }; - } else { - return { - pathname: location, - search: '', - hash: '', - state, - key: this.getRandomKey(), - }; } } + private createLocationFromString(path: string, state?: S): Location<S> { + return { + pathname: path, + search: '', + hash: '', + state, + key: this.getRandomKey(), + }; + } + private getRandomKey() { return Math.random().toString(36).substr(8); } diff --git a/gui/src/renderer/lib/routes.ts b/gui/src/renderer/lib/routes.ts index dee83c2a42..8a63cd6de0 100644 --- a/gui/src/renderer/lib/routes.ts +++ b/gui/src/renderer/lib/routes.ts @@ -1,9 +1,13 @@ +import { generatePath } from 'react-router'; + +export type GeneratedRoutePath = { routePath: string }; + export enum RoutePath { launch = '/', login = '/login', main = '/main', redeemVoucher = '/main/voucher/redeem', - voucherSuccess = '/main/voucher/success', + voucherSuccess = '/main/voucher/success/:newExpiry/:secondsAdded', timeAdded = '/main/time-added', setupFinished = '/main/setup-finished', settings = '/settings', @@ -19,3 +23,10 @@ export enum RoutePath { selectLocation = '/select-location', filterByProvider = '/select-location/filter-by-provider', } + +export function generateRoutePath( + routePath: RoutePath, + parameters: Parameters<typeof generatePath>[1], +): GeneratedRoutePath { + return { routePath: generatePath(routePath, parameters) }; +} |
