diff options
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/renderer/app.tsx | 13 | ||||
| -rw-r--r-- | gui/src/renderer/components/AppRouter.tsx | 50 | ||||
| -rw-r--r-- | gui/src/renderer/components/ExpiredAccountAddTime.tsx | 7 | ||||
| -rw-r--r-- | gui/src/renderer/components/HeaderBar.tsx | 3 | ||||
| -rw-r--r-- | gui/src/renderer/components/MainView.tsx | 3 | ||||
| -rw-r--r-- | gui/src/renderer/containers/AdvancedSettingsPage.tsx | 5 | ||||
| -rw-r--r-- | gui/src/renderer/containers/ConnectPage.tsx | 3 | ||||
| -rw-r--r-- | gui/src/renderer/containers/ExpiredAccountErrorViewContainer.tsx | 3 | ||||
| -rw-r--r-- | gui/src/renderer/containers/SettingsPage.tsx | 11 | ||||
| -rw-r--r-- | gui/src/renderer/lib/history.tsx | 15 | ||||
| -rw-r--r-- | gui/src/renderer/lib/routes.ts | 18 |
11 files changed, 80 insertions, 51 deletions
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index eb68ed963b..a92ffb2e8a 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -3,9 +3,9 @@ import { Provider } from 'react-redux'; import { Router } from 'react-router'; import { bindActionCreators } from 'redux'; +import AppRouter from './components/AppRouter'; import ErrorBoundary from './components/ErrorBoundary'; import { AppContext } from './context'; -import AppRoutes from './routes'; import accountActions from './redux/account/actions'; import connectionActions from './redux/connection/actions'; @@ -46,6 +46,7 @@ import { } from '../shared/daemon-rpc-types'; import { LogLevel } from '../shared/logging-types'; import IpcOutput from './lib/logging'; +import { RoutePath } from './lib/routes'; // This function wraps all IPC calls to catch errors and then rethrow them without the // "Uncaught Error:" prefix that's added by Electron. @@ -264,9 +265,9 @@ export default class AppRenderer { return ( <AppContext.Provider value={{ app: this }}> <Provider store={this.reduxStore}> - <Router history={this.history}> + <Router history={this.history.asHistory}> <ErrorBoundary> - <AppRoutes /> + <AppRouter /> </ErrorBoundary> </Router> </Provider> @@ -686,11 +687,11 @@ export default class AppRenderer { } } - private getNavigationBase(connectedToDaemon: boolean, accountToken?: string): string { + private getNavigationBase(connectedToDaemon: boolean, accountToken?: string): RoutePath { if (connectedToDaemon) { - return accountToken ? '/main' : '/login'; + return accountToken ? RoutePath.main : RoutePath.login; } else { - return '/'; + return RoutePath.launch; } } diff --git a/gui/src/renderer/components/AppRouter.tsx b/gui/src/renderer/components/AppRouter.tsx index 7c534597af..1816541b49 100644 --- a/gui/src/renderer/components/AppRouter.tsx +++ b/gui/src/renderer/components/AppRouter.tsx @@ -1,6 +1,6 @@ import { Action } from 'history'; import * as React from 'react'; -import { Route as ReactRouterRoute, Switch } from 'react-router'; +import { Route, Switch } from 'react-router'; import Launch from './Launch'; import KeyboardNavigation from './KeyboardNavigation'; import MainView from './MainView'; @@ -32,18 +32,6 @@ interface IAppRoutesState { action?: Action; } -interface IRouteProps<T> { - component: React.ComponentType<T>; - path: RoutePath | RoutePath[]; - exact?: boolean; -} - -function Route<T>(props: IRouteProps<T>) { - return ( - <ReactRouterRoute path={props.path} exact={props.exact ?? true} component={props.component} /> - ); -} - class AppRouter extends React.Component<IHistoryProps, IAppRoutesState> { private unobserveHistory?: () => void; @@ -86,22 +74,26 @@ class AppRouter extends React.Component<IHistoryProps, IAppRoutesState> { <TransitionContainer onTransitionEnd={this.onNavigation} {...this.state.transition}> <TransitionView viewId={location.key || ''}> <Switch key={location.key} location={location}> - <Route path={RoutePath.launch} component={Launch} /> - <Route path={RoutePath.login} component={LoginPage} /> - <Route path={RoutePath.main} component={MainView} /> - <Route path={RoutePath.redeemVoucher} component={VoucherInput} /> - <Route path={RoutePath.voucherSuccess} component={VoucherVerificationSuccess} /> - <Route path={RoutePath.timeAdded} component={TimeAdded} /> - <Route path={RoutePath.setupFinished} component={SetupFinished} /> - <Route path={RoutePath.settings} component={SettingsPage} /> - <Route path={RoutePath.selectLanguage} component={SelectLanguagePage} /> - <Route path={RoutePath.accountSettings} component={AccountPage} /> - <Route path={RoutePath.preferences} component={PreferencesPage} /> - <Route path={RoutePath.advancedSettings} component={AdvancedSettingsPage} /> - <Route path={RoutePath.wireguardKeys} component={WireguardKeysPage} /> - <Route path={RoutePath.splitTunneling} component={SplitTunnelingSettings} /> - <Route path={RoutePath.support} component={SupportPage} /> - <Route path={RoutePath.selectLocation} component={SelectLocationPage} /> + <Route exact path={RoutePath.launch} component={Launch} /> + <Route exact path={RoutePath.login} component={LoginPage} /> + <Route exact path={RoutePath.main} component={MainView} /> + <Route exact path={RoutePath.redeemVoucher} component={VoucherInput} /> + <Route + exact + path={RoutePath.voucherSuccess} + component={VoucherVerificationSuccess} + /> + <Route exact path={RoutePath.timeAdded} component={TimeAdded} /> + <Route exact path={RoutePath.setupFinished} component={SetupFinished} /> + <Route exact path={RoutePath.settings} component={SettingsPage} /> + <Route exact path={RoutePath.selectLanguage} component={SelectLanguagePage} /> + <Route exact path={RoutePath.accountSettings} component={AccountPage} /> + <Route exact path={RoutePath.preferences} component={PreferencesPage} /> + <Route exact path={RoutePath.advancedSettings} component={AdvancedSettingsPage} /> + <Route exact path={RoutePath.wireguardKeys} component={WireguardKeysPage} /> + <Route exact path={RoutePath.splitTunneling} component={SplitTunnelingSettings} /> + <Route exact path={RoutePath.support} component={SupportPage} /> + <Route exact path={RoutePath.selectLocation} component={SelectLocationPage} /> </Switch> </TransitionView> </TransitionContainer> diff --git a/gui/src/renderer/components/ExpiredAccountAddTime.tsx b/gui/src/renderer/components/ExpiredAccountAddTime.tsx index 24c335a551..43c2a4903f 100644 --- a/gui/src/renderer/components/ExpiredAccountAddTime.tsx +++ b/gui/src/renderer/components/ExpiredAccountAddTime.tsx @@ -8,6 +8,7 @@ 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 account from '../redux/account/actions'; import { IReduxState } from '../redux/store'; import * as AppButton from './AppButton'; @@ -82,7 +83,7 @@ export function VoucherInput() { const history = useHistory(); const onSuccess = useCallback(() => { - history.push('/main/voucher/success'); + history.push(RoutePath.voucherSuccess); }, [history]); const navigateBack = useCallback(() => { @@ -138,7 +139,7 @@ export function TimeAdded(props: ITimeAddedProps) { const navigateToSetupFinished = useCallback(() => { if (isNewAccount) { - history.push('/main/setup-finished'); + history.push(RoutePath.setupFinished); } else { finish(); } @@ -263,7 +264,7 @@ function useFinishedCallback() { loggedIn(); } - history.reset('/main', undefined, transitions.push); + history.reset(RoutePath.main, undefined, transitions.push); }, [isNewAccount, loggedIn, history]); return callback; diff --git a/gui/src/renderer/components/HeaderBar.tsx b/gui/src/renderer/components/HeaderBar.tsx index 35d2c2083a..42b074eaa3 100644 --- a/gui/src/renderer/components/HeaderBar.tsx +++ b/gui/src/renderer/components/HeaderBar.tsx @@ -9,6 +9,7 @@ import { IReduxState } from '../redux/store'; import { FocusFallback } from './Focus'; import { sourceSansPro } from './common-styles'; import ImageView from './ImageView'; +import { RoutePath } from '../lib/routes'; export enum HeaderBarStyle { default = 'default', @@ -103,7 +104,7 @@ export function HeaderBarSettingsButton() { const history = useHistory(); const openSettings = useCallback(() => { - history.show('/settings'); + history.show(RoutePath.settings); }, [history]); return ( diff --git a/gui/src/renderer/components/MainView.tsx b/gui/src/renderer/components/MainView.tsx index 3891a6e48b..eff5802666 100644 --- a/gui/src/renderer/components/MainView.tsx +++ b/gui/src/renderer/components/MainView.tsx @@ -5,6 +5,7 @@ import { IReduxState } from '../redux/store'; import ConnectPage from '../containers/ConnectPage'; import ExpiredAccountErrorViewContainer from '../containers/ExpiredAccountErrorViewContainer'; import { useHistory } from '../lib/history'; +import { RoutePath } from '../lib/routes'; export default function MainView() { const history = useHistory(); @@ -20,7 +21,7 @@ export default function MainView() { if (accountHasExpired) { setShowAccountExpired(true); } else if (showAccountExpired && !accountHasExpired) { - history.push('/main/time-added'); + history.push(RoutePath.timeAdded); } }, [showAccountExpired, accountHasExpired]); diff --git a/gui/src/renderer/containers/AdvancedSettingsPage.tsx b/gui/src/renderer/containers/AdvancedSettingsPage.tsx index 36a1a77963..d16f193ce0 100644 --- a/gui/src/renderer/containers/AdvancedSettingsPage.tsx +++ b/gui/src/renderer/containers/AdvancedSettingsPage.tsx @@ -11,6 +11,7 @@ import AdvancedSettings from '../components/AdvancedSettings'; import withAppContext, { IAppContext } from '../context'; import { IHistoryProps, withHistory } from '../lib/history'; +import { RoutePath } from '../lib/routes'; import { RelaySettingsRedux } from '../redux/settings/reducers'; import { IReduxState, ReduxDispatch } from '../redux/store'; @@ -163,8 +164,8 @@ const mapDispatchToProps = (_dispatch: ReduxDispatch, props: IHistoryProps & IAp return props.app.setDnsOptions(dns); }, - onViewWireguardKeys: () => props.history.push('/settings/advanced/wireguard-keys'), - onViewSplitTunneling: () => props.history.push('/settings/advanced/split-tunneling'), + onViewWireguardKeys: () => props.history.push(RoutePath.wireguardKeys), + onViewSplitTunneling: () => props.history.push(RoutePath.splitTunneling), }; }; diff --git a/gui/src/renderer/containers/ConnectPage.tsx b/gui/src/renderer/containers/ConnectPage.tsx index d7197095f1..2069b4012b 100644 --- a/gui/src/renderer/containers/ConnectPage.tsx +++ b/gui/src/renderer/containers/ConnectPage.tsx @@ -5,6 +5,7 @@ import log from '../../shared/logging'; import Connect from '../components/Connect'; import withAppContext, { IAppContext } from '../context'; import { IHistoryProps, withHistory } from '../lib/history'; +import { RoutePath } from '../lib/routes'; import { IRelayLocationRedux, RelaySettingsRedux } from '../redux/settings/reducers'; import { IReduxState, ReduxDispatch } from '../redux/store'; @@ -74,7 +75,7 @@ const mapStateToProps = (state: IReduxState) => { const mapDispatchToProps = (_dispatch: ReduxDispatch, props: IHistoryProps & IAppContext) => { return { onSelectLocation: () => { - props.history.show('/select-location'); + props.history.show(RoutePath.selectLocation); }, onConnect: async () => { try { diff --git a/gui/src/renderer/containers/ExpiredAccountErrorViewContainer.tsx b/gui/src/renderer/containers/ExpiredAccountErrorViewContainer.tsx index 372f9607c9..e5c56e7f28 100644 --- a/gui/src/renderer/containers/ExpiredAccountErrorViewContainer.tsx +++ b/gui/src/renderer/containers/ExpiredAccountErrorViewContainer.tsx @@ -5,6 +5,7 @@ import { IHistoryProps, withHistory } from '../lib/history'; import withAppContext, { IAppContext } from '../context'; import { IReduxState, ReduxDispatch } from '../redux/store'; +import { RoutePath } from '../lib/routes'; const mapStateToProps = (state: IReduxState) => ({ accountToken: state.account.accountToken, @@ -31,7 +32,7 @@ const mapDispatchToProps = (_dispatch: ReduxDispatch, props: IHistoryProps & IAp } }, navigateToRedeemVoucher: () => { - props.history.push('/main/voucher/redeem'); + props.history.push(RoutePath.redeemVoucher); }, }; }; diff --git a/gui/src/renderer/containers/SettingsPage.tsx b/gui/src/renderer/containers/SettingsPage.tsx index 57ded8cd24..da237abd23 100644 --- a/gui/src/renderer/containers/SettingsPage.tsx +++ b/gui/src/renderer/containers/SettingsPage.tsx @@ -2,6 +2,7 @@ import { connect } from 'react-redux'; import Settings from '../components/Settings'; import withAppContext, { IAppContext } from '../context'; import { IHistoryProps, withHistory } from '../lib/history'; +import { RoutePath } from '../lib/routes'; import { IReduxState, ReduxDispatch } from '../redux/store'; const mapStateToProps = (state: IReduxState, props: IAppContext) => ({ @@ -20,11 +21,11 @@ const mapDispatchToProps = (_dispatch: ReduxDispatch, props: IHistoryProps & IAp return { onQuit: () => props.app.quit(), onClose: () => props.history.dismiss(), - onViewSelectLanguage: () => props.history.push('/settings/language'), - onViewAccount: () => props.history.push('/settings/account'), - onViewSupport: () => props.history.push('/settings/support'), - onViewPreferences: () => props.history.push('/settings/preferences'), - onViewAdvancedSettings: () => props.history.push('/settings/advanced'), + onViewSelectLanguage: () => props.history.push(RoutePath.selectLanguage), + onViewAccount: () => props.history.push(RoutePath.accountSettings), + onViewSupport: () => props.history.push(RoutePath.support), + onViewPreferences: () => props.history.push(RoutePath.preferences), + onViewAdvancedSettings: () => props.history.push(RoutePath.advancedSettings), onExternalLink: (url: string) => props.app.openUrl(url), updateAccountData: () => props.app.updateAccountData(), }; diff --git a/gui/src/renderer/lib/history.tsx b/gui/src/renderer/lib/history.tsx index 13968e29b9..a391e70fee 100644 --- a/gui/src/renderer/lib/history.tsx +++ b/gui/src/renderer/lib/history.tsx @@ -1,6 +1,7 @@ -import { Location, Action, LocationDescriptor } from 'history'; +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'; export interface ITransitionSpecification { name: string; @@ -37,6 +38,8 @@ export const transitions: ITransitionMap = { }, }; +type LocationDescriptor<S> = RoutePath | LocationDescriptorObject<S>; + type LocationListener<S = unknown> = ( location: Location<S>, action: Action, @@ -53,7 +56,7 @@ export default class History { private index = 0; private lastAction: Action = 'POP'; - public constructor(location: string | Location<S>, state?: S) { + public constructor(location: LocationDescriptor<S>, state?: S) { this.entries = [this.createLocation(location, state)]; } @@ -114,6 +117,14 @@ export default class History { return nextIndex >= 0 && nextIndex < this.entries.length; } + // This returns this object casted as History from the History module. The difference between this + // one and the one in the history module is that this one has stricter types for the paths. + // Instead of accepting any string it's limited to the paths we actually support. But this history + // implementation would handle any string as expected. + public get asHistory(): OriginalHistory { + return this as OriginalHistory; + } + public block(): never { throw Error('Not implemented'); } diff --git a/gui/src/renderer/lib/routes.ts b/gui/src/renderer/lib/routes.ts new file mode 100644 index 0000000000..bf8e6e1f60 --- /dev/null +++ b/gui/src/renderer/lib/routes.ts @@ -0,0 +1,18 @@ +export enum RoutePath { + launch = '/', + login = '/login', + main = '/main', + redeemVoucher = '/main/voucher/redeem', + voucherSuccess = '/main/voucher/success', + timeAdded = '/main/time-added', + setupFinished = '/main/setup-finished', + settings = '/settings', + selectLanguage = '/settings/language', + accountSettings = '/settings/account', + preferences = '/settings/preferences', + advancedSettings = '/settings/advanced', + wireguardKeys = '/settings/advanced/wireguard-keys', + splitTunneling = '/settings/advanced/split-tunneling', + support = '/settings/support', + selectLocation = '/select-location', +} |
