diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2023-07-14 09:51:37 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2023-08-28 16:07:31 +0200 |
| commit | fd67444fe038ac97c553493614b357745834bdb7 (patch) | |
| tree | b834d6bc2f370fcfa735d2d43484870d3c87b556 /gui/src/renderer/app.tsx | |
| parent | bab7783eee1ad89ecbe45fc061cea59804400740 (diff) | |
| download | mullvadvpn-fd67444fe038ac97c553493614b357745834bdb7.tar.xz mullvadvpn-fd67444fe038ac97c553493614b357745834bdb7.zip | |
Replace out of time view when adding time
Diffstat (limited to 'gui/src/renderer/app.tsx')
| -rw-r--r-- | gui/src/renderer/app.tsx | 106 |
1 files changed, 73 insertions, 33 deletions
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index 6efcd81887..0dfda5d688 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -2,6 +2,7 @@ import { batch, Provider } from 'react-redux'; import { Router } from 'react-router'; import { bindActionCreators } from 'redux'; +import { hasExpired } from '../shared/account-expiry'; import { ILinuxSplitTunnelingApplication, IWindowsApplication } from '../shared/application-types'; import { AccountToken, @@ -204,7 +205,6 @@ export default class AppRenderer { initialState.translations.relayLocations, ); - this.setAccountExpiry(initialState.accountData?.expiry); this.setSettings(initialState.settings); this.setIsPerformingPostUpgrade(initialState.isPerformingPostUpgrade); @@ -219,6 +219,8 @@ export default class AppRenderer { initialState.navigationHistory !== undefined, ); } + // Login state and account needs to be set before expiry. + this.setAccountExpiry(initialState.accountData?.expiry); this.setAccountHistory(initialState.accountHistory); this.setTunnelState(initialState.tunnelState); @@ -648,40 +650,54 @@ export default class AppRenderer { const nextPath = this.getNavigationBase() as RoutePath; if (pathname !== nextPath) { - // First level contains the possible next locations and the second level contains the - // possible current locations. - const navigationTransitions: Partial< - Record<RoutePath, Partial<Record<RoutePath | '*', ITransitionSpecification>>> - > = { - [RoutePath.launch]: { - [RoutePath.login]: transitions.pop, - [RoutePath.main]: transitions.pop, - '*': transitions.dismiss, - }, - [RoutePath.login]: { - [RoutePath.launch]: transitions.push, - [RoutePath.main]: transitions.pop, - [RoutePath.deviceRevoked]: transitions.pop, - '*': transitions.dismiss, - }, - [RoutePath.main]: { - [RoutePath.launch]: transitions.push, - [RoutePath.login]: transitions.push, - [RoutePath.tooManyDevices]: transitions.push, - '*': transitions.dismiss, - }, - [RoutePath.deviceRevoked]: { - '*': transitions.pop, - }, - }; - - const transition = - navigationTransitions[nextPath]?.[pathname] ?? navigationTransitions[nextPath]?.['*']; + const transition = this.getNavigationTransition(pathname, nextPath); this.history.reset(nextPath, { transition }); } } } + private getNavigationTransition(prevPath: RoutePath, nextPath: RoutePath) { + // First level contains the possible next locations and the second level contains the + // possible current locations. + const navigationTransitions: Partial< + Record<RoutePath, Partial<Record<RoutePath | '*', ITransitionSpecification>>> + > = { + [RoutePath.launch]: { + [RoutePath.login]: transitions.pop, + [RoutePath.main]: transitions.pop, + '*': transitions.dismiss, + }, + [RoutePath.login]: { + [RoutePath.launch]: transitions.push, + [RoutePath.main]: transitions.pop, + [RoutePath.deviceRevoked]: transitions.pop, + '*': transitions.dismiss, + }, + [RoutePath.main]: { + [RoutePath.launch]: transitions.push, + [RoutePath.login]: transitions.push, + [RoutePath.tooManyDevices]: transitions.push, + '*': transitions.dismiss, + }, + [RoutePath.expired]: { + [RoutePath.launch]: transitions.push, + [RoutePath.login]: transitions.push, + [RoutePath.tooManyDevices]: transitions.push, + '*': transitions.dismiss, + }, + [RoutePath.timeAdded]: { + [RoutePath.expired]: transitions.push, + [RoutePath.redeemVoucher]: transitions.push, + '*': transitions.dismiss, + }, + [RoutePath.deviceRevoked]: { + '*': transitions.pop, + }, + }; + + return navigationTransitions[nextPath]?.[prevPath] ?? navigationTransitions[nextPath]?.['*']; + } + private getNavigationBase(): RoutePath { if (this.connectedToDaemon && this.deviceState !== undefined) { const loginState = this.reduxStore.getState().account.status; @@ -689,10 +705,17 @@ export default class AppRenderer { if (deviceRevoked) { return RoutePath.deviceRevoked; - } else if (this.isLoggedIn()) { - return RoutePath.main; - } else { + } else if (!this.isLoggedIn()) { return RoutePath.login; + } else if ( + loginState.type === 'ok' && + (loginState.expiredState === 'expired' || loginState.method === 'new_account') + ) { + return RoutePath.expired; + } else if (loginState.type === 'ok' && loginState.expiredState === 'time_added') { + return RoutePath.timeAdded; + } else { + return RoutePath.main; } } else { return RoutePath.launch; @@ -884,7 +907,24 @@ export default class AppRenderer { } private setAccountExpiry(expiry?: string) { + const state = this.reduxStore.getState(); + const previousExpiry = state.account.expiry; this.reduxActions.account.updateAccountExpiry(expiry); + + const expired = expiry !== undefined && hasExpired(expiry); + if ( + this.history && + state.account.status.type === 'ok' && + expiry !== undefined && + expiry !== previousExpiry && + ((state.account.status.expiredState === undefined && expired) || + (state.account.status.expiredState === 'expired' && !expired)) + ) { + const prevPath = this.history.location.pathname as RoutePath; + const nextPath = expired ? RoutePath.expired : RoutePath.timeAdded; + const transition = this.getNavigationTransition(prevPath, nextPath); + this.history.replaceRoot(nextPath, { transition }); + } } private storeAutoStart(autoStart: boolean) { |
