summaryrefslogtreecommitdiffhomepage
path: root/gui/src/renderer/components/AppRouter.tsx
blob: 9921109d23a34e5891659fabb2ef721b4f5f4beb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { Action } from 'history';
import * as React from 'react';
import { Route, Switch } from 'react-router';
import Launch from './Launch';
import KeyboardNavigation from './KeyboardNavigation';
import MainView from './MainView';
import Focus, { IFocusHandle } from './Focus';
import SplitTunnelingSettings from './SplitTunnelingSettings';
import TransitionContainer, { TransitionView } from './TransitionContainer';
import AccountPage from '../containers/AccountPage';
import AdvancedSettingsPage from '../containers/AdvancedSettingsPage';
import LoginPage from '../containers/LoginPage';
import OpenVPNSettingsPage from '../containers/OpenVPNSettingsPage';
import PlatformWindowContainer from '../containers/PlatformWindowContainer';
import PreferencesPage from '../containers/PreferencesPage';
import SelectLanguagePage from '../containers/SelectLanguagePage';
import SelectLocationPage from '../containers/SelectLocationPage';
import SettingsPage from '../containers/SettingsPage';
import SupportPage from '../containers/SupportPage';
import WireguardKeysPage from '../containers/WireguardKeysPage';
import WireguardSettingsPage from '../containers/WireguardSettingsPage';
import { IHistoryProps, ITransitionSpecification, transitions, withHistory } from '../lib/history';
import {
  SetupFinished,
  TimeAdded,
  VoucherInput,
  VoucherVerificationSuccess,
} from './ExpiredAccountAddTime';
import { RoutePath } from '../lib/routes';
import FilterByProvider from './FilterByProvider';

interface IAppRoutesState {
  currentLocation: IHistoryProps['history']['location'];
  transition: ITransitionSpecification;
  action?: Action;
}

class AppRouter extends React.Component<IHistoryProps, IAppRoutesState> {
  private unobserveHistory?: () => void;

  private focusRef = React.createRef<IFocusHandle>();

  constructor(props: IHistoryProps) {
    super(props);

    this.state = {
      currentLocation: props.history.location,
      transition: transitions.none,
    };
  }

  public componentDidMount() {
    // React throttles updates, so it's impossible to capture the intermediate navigation without
    // listening to the history directly.
    this.unobserveHistory = this.props.history.listen((location, action, transition) => {
      this.setState({
        currentLocation: location,
        transition,
        action,
      });
    });
  }

  public componentWillUnmount() {
    if (this.unobserveHistory) {
      this.unobserveHistory();
    }
  }

  public render() {
    const location = this.state.currentLocation;

    return (
      <PlatformWindowContainer>
        <KeyboardNavigation>
          <Focus ref={this.focusRef}>
            <TransitionContainer onTransitionEnd={this.onNavigation} {...this.state.transition}>
              <TransitionView viewId={location.key || ''}>
                <Switch key={location.key} location={location}>
                  <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.wireguardSettings}
                    component={WireguardSettingsPage}
                  />
                  <Route exact path={RoutePath.wireguardKeys} component={WireguardKeysPage} />
                  <Route exact path={RoutePath.openVpnSettings} component={OpenVPNSettingsPage} />
                  <Route exact path={RoutePath.splitTunneling} component={SplitTunnelingSettings} />
                  <Route exact path={RoutePath.support} component={SupportPage} />
                  <Route exact path={RoutePath.selectLocation} component={SelectLocationPage} />
                  <Route exact path={RoutePath.filterByProvider} component={FilterByProvider} />
                </Switch>
              </TransitionView>
            </TransitionContainer>
          </Focus>
        </KeyboardNavigation>
      </PlatformWindowContainer>
    );
  }

  private onNavigation = () => {
    this.focusRef.current?.resetFocus();
  };
}

const AppRoutesWithRouter = withHistory(AppRouter);

export default AppRoutesWithRouter;