summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-01-18 21:19:39 +0100
committerOskar Nyberg <oskar@mullvad.net>2022-01-27 10:39:37 +0100
commit270a9fbc30a79e60283349274684e6eb6d5ff523 (patch)
treea18a54c7853f161d178e42e22420834a30bd7277 /gui/src
parentbc7ebf12c08b0fa9a0d8ec2ec9db026b24a57080 (diff)
downloadmullvadvpn-270a9fbc30a79e60283349274684e6eb6d5ff523.tar.xz
mullvadvpn-270a9fbc30a79e60283349274684e6eb6d5ff523.zip
Wrap entire app in ModalContainer
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/app.tsx14
-rw-r--r--gui/src/renderer/components/Account.tsx141
-rw-r--r--gui/src/renderer/components/AdvancedSettings.tsx253
-rw-r--r--gui/src/renderer/components/AppRouter.tsx73
-rw-r--r--gui/src/renderer/components/Connect.tsx11
-rw-r--r--gui/src/renderer/components/ErrorBoundary.tsx7
-rw-r--r--gui/src/renderer/components/ExpiredAccountErrorView.tsx48
-rw-r--r--gui/src/renderer/components/OpenVPNSettings.tsx276
-rw-r--r--gui/src/renderer/components/Preferences.tsx507
-rw-r--r--gui/src/renderer/components/SplitTunnelingSettings.tsx64
-rw-r--r--gui/src/renderer/components/Support.tsx56
-rw-r--r--gui/src/renderer/components/WireguardSettings.tsx320
12 files changed, 867 insertions, 903 deletions
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index 7b4b63c969..23b2f36810 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -5,6 +5,7 @@ import { bindActionCreators } from 'redux';
import AppRouter from './components/AppRouter';
import MacOsScrollbarDetection from './components/MacOsScrollbarDetection';
import ErrorBoundary from './components/ErrorBoundary';
+import PlatformWindowContainer from './containers/PlatformWindowContainer';
import { AppContext } from './context';
import accountActions from './redux/account/actions';
@@ -45,6 +46,7 @@ import {
import { LogLevel } from '../shared/logging-types';
import IpcOutput from './lib/logging';
import { RoutePath } from './lib/routes';
+import { ModalContainer } from './components/Modal';
const IpcRendererEventChannel = window.ipc;
@@ -248,10 +250,14 @@ export default class AppRenderer {
<AppContext.Provider value={{ app: this }}>
<Provider store={this.reduxStore}>
<Router history={this.history.asHistory}>
- <ErrorBoundary>
- <AppRouter />
- {window.env.platform === 'darwin' && <MacOsScrollbarDetection />}
- </ErrorBoundary>
+ <PlatformWindowContainer>
+ <ErrorBoundary>
+ <ModalContainer>
+ <AppRouter />
+ {window.env.platform === 'darwin' && <MacOsScrollbarDetection />}
+ </ModalContainer>
+ </ErrorBoundary>
+ </PlatformWindowContainer>
</Router>
</Provider>
</AppContext.Provider>
diff --git a/gui/src/renderer/components/Account.tsx b/gui/src/renderer/components/Account.tsx
index 02e2b9f081..86a70db271 100644
--- a/gui/src/renderer/components/Account.tsx
+++ b/gui/src/renderer/components/Account.tsx
@@ -17,7 +17,6 @@ import AccountTokenLabel from './AccountTokenLabel';
import * as AppButton from './AppButton';
import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGroup';
import { Layout } from './Layout';
-import { ModalContainer } from './Modal';
import { BackBarItem, NavigationBar, NavigationItems, TitleBarItem } from './NavigationBar';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
@@ -41,84 +40,80 @@ export default class Account extends React.Component<IProps> {
public render() {
return (
- <ModalContainer>
- <Layout>
- <StyledContainer>
- <NavigationBar>
- <NavigationItems>
- <BackBarItem action={this.props.onClose}>
- {
- // TRANSLATORS: Back button in navigation bar
- messages.pgettext('navigation-bar', 'Settings')
- }
- </BackBarItem>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('account-view', 'Account')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <Layout>
+ <StyledContainer>
+ <NavigationBar>
+ <NavigationItems>
+ <BackBarItem action={this.props.onClose}>
+ {
+ // TRANSLATORS: Back button in navigation bar
+ messages.pgettext('navigation-bar', 'Settings')
+ }
+ </BackBarItem>
+ <TitleBarItem>
+ {
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('account-view', 'Account')
+ }
+ </TitleBarItem>
+ </NavigationItems>
+ </NavigationBar>
- <AccountContainer>
- <SettingsHeader>
- <HeaderTitle>{messages.pgettext('account-view', 'Account')}</HeaderTitle>
- </SettingsHeader>
+ <AccountContainer>
+ <SettingsHeader>
+ <HeaderTitle>{messages.pgettext('account-view', 'Account')}</HeaderTitle>
+ </SettingsHeader>
- <AccountRows>
- <AccountRow>
- <AccountRowLabel>
- {messages.pgettext('account-view', 'Account number')}
- </AccountRowLabel>
- <AccountRowValue
- as={AccountTokenLabel}
- accountToken={this.props.accountToken || ''}
- />
- </AccountRow>
+ <AccountRows>
+ <AccountRow>
+ <AccountRowLabel>
+ {messages.pgettext('account-view', 'Account number')}
+ </AccountRowLabel>
+ <AccountRowValue
+ as={AccountTokenLabel}
+ accountToken={this.props.accountToken || ''}
+ />
+ </AccountRow>
- <AccountRow>
- <AccountRowLabel>
- {messages.pgettext('account-view', 'Paid until')}
- </AccountRowLabel>
- <FormattedAccountExpiry
- expiry={this.props.accountExpiry}
- locale={this.props.expiryLocale}
- />
- </AccountRow>
- </AccountRows>
+ <AccountRow>
+ <AccountRowLabel>{messages.pgettext('account-view', 'Paid until')}</AccountRowLabel>
+ <FormattedAccountExpiry
+ expiry={this.props.accountExpiry}
+ locale={this.props.expiryLocale}
+ />
+ </AccountRow>
+ </AccountRows>
- <AccountFooter>
- <AppButton.BlockingButton
- disabled={this.props.isOffline}
- onClick={this.props.onBuyMore}>
- <AriaDescriptionGroup>
- <AriaDescribed>
- <StyledBuyCreditButton>
- <AppButton.Label>{messages.gettext('Buy more credit')}</AppButton.Label>
- <AriaDescription>
- <AppButton.Icon
- source="icon-extLink"
- height={16}
- width={16}
- aria-label={messages.pgettext('accessibility', 'Opens externally')}
- />
- </AriaDescription>
- </StyledBuyCreditButton>
- </AriaDescribed>
- </AriaDescriptionGroup>
- </AppButton.BlockingButton>
+ <AccountFooter>
+ <AppButton.BlockingButton
+ disabled={this.props.isOffline}
+ onClick={this.props.onBuyMore}>
+ <AriaDescriptionGroup>
+ <AriaDescribed>
+ <StyledBuyCreditButton>
+ <AppButton.Label>{messages.gettext('Buy more credit')}</AppButton.Label>
+ <AriaDescription>
+ <AppButton.Icon
+ source="icon-extLink"
+ height={16}
+ width={16}
+ aria-label={messages.pgettext('accessibility', 'Opens externally')}
+ />
+ </AriaDescription>
+ </StyledBuyCreditButton>
+ </AriaDescribed>
+ </AriaDescriptionGroup>
+ </AppButton.BlockingButton>
- <StyledRedeemVoucherButton />
+ <StyledRedeemVoucherButton />
- <AppButton.RedButton onClick={this.props.onLogout}>
- {messages.pgettext('account-view', 'Log out')}
- </AppButton.RedButton>
- </AccountFooter>
- </AccountContainer>
- </StyledContainer>
- </Layout>
- </ModalContainer>
+ <AppButton.RedButton onClick={this.props.onLogout}>
+ {messages.pgettext('account-view', 'Log out')}
+ </AppButton.RedButton>
+ </AccountFooter>
+ </AccountContainer>
+ </StyledContainer>
+ </Layout>
);
}
}
diff --git a/gui/src/renderer/components/AdvancedSettings.tsx b/gui/src/renderer/components/AdvancedSettings.tsx
index cbd5c6d7f7..084459b79c 100644
--- a/gui/src/renderer/components/AdvancedSettings.tsx
+++ b/gui/src/renderer/components/AdvancedSettings.tsx
@@ -15,7 +15,7 @@ import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGro
import * as Cell from './cell';
import CustomDnsSettings from './CustomDnsSettings';
import { Layout, SettingsContainer } from './Layout';
-import { ModalAlert, ModalAlertType, ModalContainer, ModalMessage } from './Modal';
+import { ModalAlert, ModalAlertType, ModalMessage } from './Modal';
import {
BackBarItem,
NavigationBar,
@@ -58,150 +58,143 @@ export default class AdvancedSettings extends React.Component<IProps, IState> {
const hasWireguardKey = this.props.wireguardKeyState.type === 'key-set';
return (
- <ModalContainer>
- <Layout>
- <SettingsContainer>
- <NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <BackBarItem action={this.props.onClose}>
- {
- // TRANSLATORS: Back button in navigation bar
- messages.pgettext('navigation-bar', 'Settings')
- }
- </BackBarItem>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('advanced-settings-nav', 'Advanced')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <Layout>
+ <SettingsContainer>
+ <NavigationContainer>
+ <NavigationBar>
+ <NavigationItems>
+ <BackBarItem action={this.props.onClose}>
+ {
+ // TRANSLATORS: Back button in navigation bar
+ messages.pgettext('navigation-bar', 'Settings')
+ }
+ </BackBarItem>
+ <TitleBarItem>
+ {
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('advanced-settings-nav', 'Advanced')
+ }
+ </TitleBarItem>
+ </NavigationItems>
+ </NavigationBar>
- <StyledNavigationScrollbars>
- <SettingsHeader>
- <HeaderTitle>
- {messages.pgettext('advanced-settings-view', 'Advanced')}
- </HeaderTitle>
- </SettingsHeader>
+ <StyledNavigationScrollbars>
+ <SettingsHeader>
+ <HeaderTitle>{messages.pgettext('advanced-settings-view', 'Advanced')}</HeaderTitle>
+ </SettingsHeader>
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('advanced-settings-view', 'Enable IPv6')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={this.props.enableIpv6}
- onChange={this.props.setEnableIpv6}
- />
- </AriaInput>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {messages.pgettext(
- 'advanced-settings-view',
- 'Enable IPv6 communication through the tunnel.',
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('advanced-settings-view', 'Enable IPv6')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch isOn={this.props.enableIpv6} onChange={this.props.setEnableIpv6} />
+ </AriaInput>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {messages.pgettext(
+ 'advanced-settings-view',
+ 'Enable IPv6 communication through the tunnel.',
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('advanced-settings-view', 'Always require VPN')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- ref={this.blockWhenDisconnectedRef}
- isOn={this.props.blockWhenDisconnected}
- onChange={this.setBlockWhenDisconnected}
- />
- </AriaInput>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {messages.pgettext(
- 'advanced-settings-view',
- 'If you disconnect or quit the app, this setting will block your internet.',
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
-
- {(window.env.platform === 'linux' || window.env.platform === 'win32') && (
- <Cell.CellButtonGroup>
- <Cell.CellButton onClick={this.props.onViewSplitTunneling}>
- <Cell.Label>
- {messages.pgettext('advanced-settings-view', 'Split tunneling')}
- </Cell.Label>
- <Cell.Icon height={12} width={7} source="icon-chevron" />
- </Cell.CellButton>
- </Cell.CellButtonGroup>
- )}
-
- <AriaInputGroup>
- <StyledTunnelProtocolContainer>
- <StyledSelectorForFooter
- title={messages.pgettext('advanced-settings-view', 'Tunnel protocol')}
- values={this.tunnelProtocolItems(hasWireguardKey)}
- value={this.props.tunnelProtocol}
- onSelect={this.onSelectTunnelProtocol}
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('advanced-settings-view', 'Always require VPN')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ ref={this.blockWhenDisconnectedRef}
+ isOn={this.props.blockWhenDisconnected}
+ onChange={this.setBlockWhenDisconnected}
/>
- {!hasWireguardKey && (
- <StyledNoWireguardKeyErrorContainer>
- <AriaDescription>
- <StyledNoWireguardKeyError>
- {messages.pgettext(
- 'advanced-settings-view',
- 'To enable WireGuard, generate a key under the "WireGuard key" setting below.',
- )}
- </StyledNoWireguardKeyError>
- </AriaDescription>
- </StyledNoWireguardKeyErrorContainer>
- )}
- </StyledTunnelProtocolContainer>
- </AriaInputGroup>
+ </AriaInput>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {messages.pgettext(
+ 'advanced-settings-view',
+ 'If you disconnect or quit the app, this setting will block your internet.',
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+ {(window.env.platform === 'linux' || window.env.platform === 'win32') && (
<Cell.CellButtonGroup>
- <Cell.CellButton
- onClick={this.props.onViewWireguardSettings}
- disabled={this.props.tunnelProtocol === 'openvpn'}>
- <Cell.Label>
- {messages.pgettext('advanced-settings-view', 'WireGuard settings')}
- </Cell.Label>
- <Cell.Icon height={12} width={7} source="icon-chevron" />
- </Cell.CellButton>
-
- <Cell.CellButton
- onClick={this.props.onViewOpenVpnSettings}
- disabled={this.props.tunnelProtocol === 'wireguard'}>
+ <Cell.CellButton onClick={this.props.onViewSplitTunneling}>
<Cell.Label>
- {messages.pgettext('advanced-settings-view', 'OpenVPN settings')}
+ {messages.pgettext('advanced-settings-view', 'Split tunneling')}
</Cell.Label>
<Cell.Icon height={12} width={7} source="icon-chevron" />
</Cell.CellButton>
</Cell.CellButtonGroup>
+ )}
+
+ <AriaInputGroup>
+ <StyledTunnelProtocolContainer>
+ <StyledSelectorForFooter
+ title={messages.pgettext('advanced-settings-view', 'Tunnel protocol')}
+ values={this.tunnelProtocolItems(hasWireguardKey)}
+ value={this.props.tunnelProtocol}
+ onSelect={this.onSelectTunnelProtocol}
+ />
+ {!hasWireguardKey && (
+ <StyledNoWireguardKeyErrorContainer>
+ <AriaDescription>
+ <StyledNoWireguardKeyError>
+ {messages.pgettext(
+ 'advanced-settings-view',
+ 'To enable WireGuard, generate a key under the "WireGuard key" setting below.',
+ )}
+ </StyledNoWireguardKeyError>
+ </AriaDescription>
+ </StyledNoWireguardKeyErrorContainer>
+ )}
+ </StyledTunnelProtocolContainer>
+ </AriaInputGroup>
+
+ <Cell.CellButtonGroup>
+ <Cell.CellButton
+ onClick={this.props.onViewWireguardSettings}
+ disabled={this.props.tunnelProtocol === 'openvpn'}>
+ <Cell.Label>
+ {messages.pgettext('advanced-settings-view', 'WireGuard settings')}
+ </Cell.Label>
+ <Cell.Icon height={12} width={7} source="icon-chevron" />
+ </Cell.CellButton>
+
+ <Cell.CellButton
+ onClick={this.props.onViewOpenVpnSettings}
+ disabled={this.props.tunnelProtocol === 'wireguard'}>
+ <Cell.Label>
+ {messages.pgettext('advanced-settings-view', 'OpenVPN settings')}
+ </Cell.Label>
+ <Cell.Icon height={12} width={7} source="icon-chevron" />
+ </Cell.CellButton>
+ </Cell.CellButtonGroup>
- <CustomDnsSettings />
- </StyledNavigationScrollbars>
- </NavigationContainer>
- </SettingsContainer>
- </Layout>
+ <CustomDnsSettings />
+ </StyledNavigationScrollbars>
+ </NavigationContainer>
+ </SettingsContainer>
{this.state.showConfirmBlockWhenDisconnectedAlert &&
this.renderConfirmBlockWhenDisconnectedAlert()}
- </ModalContainer>
+ </Layout>
);
}
diff --git a/gui/src/renderer/components/AppRouter.tsx b/gui/src/renderer/components/AppRouter.tsx
index 9921109d23..f72de697e3 100644
--- a/gui/src/renderer/components/AppRouter.tsx
+++ b/gui/src/renderer/components/AppRouter.tsx
@@ -11,7 +11,6 @@ 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';
@@ -71,45 +70,39 @@ class AppRouter extends React.Component<IHistoryProps, IAppRoutesState> {
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>
+ <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>
);
}
diff --git a/gui/src/renderer/components/Connect.tsx b/gui/src/renderer/components/Connect.tsx
index a150da90f1..d861ab51f6 100644
--- a/gui/src/renderer/components/Connect.tsx
+++ b/gui/src/renderer/components/Connect.tsx
@@ -9,7 +9,6 @@ import { calculateHeaderBarStyle, DefaultHeaderBar } from './HeaderBar';
import ImageView from './ImageView';
import { Container, Layout } from './Layout';
import Map, { MarkerStyle, ZoomLevel } from './Map';
-import { ModalContainer } from './Modal';
import TunnelControl from './TunnelControl';
interface IProps {
@@ -85,12 +84,10 @@ export default class Connect extends React.Component<IProps, IState> {
public render() {
return (
- <ModalContainer>
- <Layout>
- <DefaultHeaderBar barStyle={calculateHeaderBarStyle(this.props.connection.status)} />
- <StyledContainer>{this.renderMap()}</StyledContainer>
- </Layout>
- </ModalContainer>
+ <Layout>
+ <DefaultHeaderBar barStyle={calculateHeaderBarStyle(this.props.connection.status)} />
+ <StyledContainer>{this.renderMap()}</StyledContainer>
+ </Layout>
);
}
diff --git a/gui/src/renderer/components/ErrorBoundary.tsx b/gui/src/renderer/components/ErrorBoundary.tsx
index d29c029c93..d9f2bf370e 100644
--- a/gui/src/renderer/components/ErrorBoundary.tsx
+++ b/gui/src/renderer/components/ErrorBoundary.tsx
@@ -3,7 +3,6 @@ import styled from 'styled-components';
import { supportEmail } from '../../config.json';
import { messages } from '../../shared/gettext';
import log from '../../shared/logging';
-import PlatformWindowContainer from '../containers/PlatformWindowContainer';
import ErrorView from './ErrorView';
interface IProps {
@@ -42,11 +41,7 @@ export default class ErrorBoundary extends React.Component<IProps, IState> {
.split('%(email)s', 2);
reachBackMessage.splice(1, 0, <Email>{supportEmail}</Email>);
- return (
- <PlatformWindowContainer>
- <ErrorView>{reachBackMessage}</ErrorView>
- </PlatformWindowContainer>
- );
+ return <ErrorView>{reachBackMessage}</ErrorView>;
} else {
return this.props.children;
}
diff --git a/gui/src/renderer/components/ExpiredAccountErrorView.tsx b/gui/src/renderer/components/ExpiredAccountErrorView.tsx
index c24c79da45..6f29b3dad2 100644
--- a/gui/src/renderer/components/ExpiredAccountErrorView.tsx
+++ b/gui/src/renderer/components/ExpiredAccountErrorView.tsx
@@ -26,7 +26,7 @@ import {
import { calculateHeaderBarStyle, HeaderBarStyle } from './HeaderBar';
import ImageView from './ImageView';
import { Layout } from './Layout';
-import { ModalAlert, ModalAlertType, ModalContainer, ModalMessage } from './Modal';
+import { ModalAlert, ModalAlertType, ModalMessage } from './Modal';
export enum RecoveryAction {
openBrowser,
@@ -65,34 +65,32 @@ export default class ExpiredAccountErrorView extends React.Component<
: calculateHeaderBarStyle(this.props.tunnelState);
return (
- <ModalContainer>
- <Layout>
- <StyledHeader barStyle={headerBarStyle} />
- <StyledCustomScrollbars fillContainer>
- <StyledContainer>
- <StyledBody>{this.renderContent()}</StyledBody>
+ <Layout>
+ <StyledHeader barStyle={headerBarStyle} />
+ <StyledCustomScrollbars fillContainer>
+ <StyledContainer>
+ <StyledBody>{this.renderContent()}</StyledBody>
- <StyledFooter>
- {this.getRecoveryAction() === RecoveryAction.disconnect && (
- <AppButton.BlockingButton onClick={this.props.onDisconnect}>
- <StyledDisconnectButton>
- {messages.pgettext('connect-view', 'Disconnect')}
- </StyledDisconnectButton>
- </AppButton.BlockingButton>
- )}
+ <StyledFooter>
+ {this.getRecoveryAction() === RecoveryAction.disconnect && (
+ <AppButton.BlockingButton onClick={this.props.onDisconnect}>
+ <StyledDisconnectButton>
+ {messages.pgettext('connect-view', 'Disconnect')}
+ </StyledDisconnectButton>
+ </AppButton.BlockingButton>
+ )}
- {this.renderExternalPaymentButton()}
+ {this.renderExternalPaymentButton()}
- <AppButton.GreenButton onClick={this.props.navigateToRedeemVoucher}>
- {messages.pgettext('connect-view', 'Redeem voucher')}
- </AppButton.GreenButton>
- </StyledFooter>
+ <AppButton.GreenButton onClick={this.props.navigateToRedeemVoucher}>
+ {messages.pgettext('connect-view', 'Redeem voucher')}
+ </AppButton.GreenButton>
+ </StyledFooter>
- {this.state.showBlockWhenDisconnectedAlert && this.renderBlockWhenDisconnectedAlert()}
- </StyledContainer>
- </StyledCustomScrollbars>
- </Layout>
- </ModalContainer>
+ {this.state.showBlockWhenDisconnectedAlert && this.renderBlockWhenDisconnectedAlert()}
+ </StyledContainer>
+ </StyledCustomScrollbars>
+ </Layout>
);
}
diff --git a/gui/src/renderer/components/OpenVPNSettings.tsx b/gui/src/renderer/components/OpenVPNSettings.tsx
index b029038d06..ce2cbe264b 100644
--- a/gui/src/renderer/components/OpenVPNSettings.tsx
+++ b/gui/src/renderer/components/OpenVPNSettings.tsx
@@ -7,7 +7,7 @@ import * as AppButton from './AppButton';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import { Layout, SettingsContainer } from './Layout';
-import { ModalAlert, ModalAlertType, ModalContainer } from './Modal';
+import { ModalAlert, ModalAlertType } from './Modal';
import {
BackBarItem,
NavigationBar,
@@ -90,155 +90,153 @@ export default class OpenVpnSettings extends React.Component<IProps, IState> {
public render() {
return (
- <ModalContainer>
- <Layout>
- <SettingsContainer>
- <NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <BackBarItem action={this.props.onClose}>
- {
- // TRANSLATORS: Back button in navigation bar
- messages.pgettext('navigation-bar', 'Advanced')
- }
- </BackBarItem>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('openvpn-settings-nav', 'OpenVPN settings')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <Layout>
+ <SettingsContainer>
+ <NavigationContainer>
+ <NavigationBar>
+ <NavigationItems>
+ <BackBarItem action={this.props.onClose}>
+ {
+ // TRANSLATORS: Back button in navigation bar
+ messages.pgettext('navigation-bar', 'Advanced')
+ }
+ </BackBarItem>
+ <TitleBarItem>
+ {
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('openvpn-settings-nav', 'OpenVPN settings')
+ }
+ </TitleBarItem>
+ </NavigationItems>
+ </NavigationBar>
- <StyledNavigationScrollbars>
- <SettingsHeader>
- <HeaderTitle>
- {messages.pgettext('openvpn-settings-view', 'OpenVPN settings')}
- </HeaderTitle>
- </SettingsHeader>
+ <StyledNavigationScrollbars>
+ <SettingsHeader>
+ <HeaderTitle>
+ {messages.pgettext('openvpn-settings-view', 'OpenVPN settings')}
+ </HeaderTitle>
+ </SettingsHeader>
- <StyledSelectorContainer>
- <AriaInputGroup>
- <Selector
- title={messages.pgettext('openvpn-settings-view', 'Transport protocol')}
- values={this.protocolItems(this.props.bridgeState !== 'on')}
- value={this.props.openvpn.protocol}
- onSelect={this.onSelectOpenvpnProtocol}
- hasFooter={this.props.bridgeState === 'on'}
- />
- {this.props.bridgeState === 'on' && (
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {formatMarkdown(
- // TRANSLATORS: This is used to instruct users how to make UDP mode
- // TRANSLATORS: available.
- messages.pgettext(
- 'openvpn-settings-view',
- 'To activate UDP, change **Bridge mode** to **Automatic** or **Off**.',
- ),
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- )}
- </AriaInputGroup>
- </StyledSelectorContainer>
-
- <StyledSelectorContainer>
- <AriaInputGroup>
- {this.props.openvpn.protocol ? (
- <Selector
- title={sprintf(
- // TRANSLATORS: The title for the port selector section.
- // TRANSLATORS: Available placeholders:
- // TRANSLATORS: %(portType)s - a selected protocol (either TCP or UDP)
- messages.pgettext('openvpn-settings-view', '%(portType)s port'),
- {
- portType: this.props.openvpn.protocol.toUpperCase(),
- },
- )}
- values={this.portItems[this.props.openvpn.protocol]}
- value={this.props.openvpn.port}
- onSelect={this.onSelectOpenVpnPort}
- />
- ) : undefined}
- </AriaInputGroup>
- </StyledSelectorContainer>
+ <StyledSelectorContainer>
+ <AriaInputGroup>
+ <Selector
+ title={messages.pgettext('openvpn-settings-view', 'Transport protocol')}
+ values={this.protocolItems(this.props.bridgeState !== 'on')}
+ value={this.props.openvpn.protocol}
+ onSelect={this.onSelectOpenvpnProtocol}
+ hasFooter={this.props.bridgeState === 'on'}
+ />
+ {this.props.bridgeState === 'on' && (
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {formatMarkdown(
+ // TRANSLATORS: This is used to instruct users how to make UDP mode
+ // TRANSLATORS: available.
+ messages.pgettext(
+ 'openvpn-settings-view',
+ 'To activate UDP, change **Bridge mode** to **Automatic** or **Off**.',
+ ),
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ )}
+ </AriaInputGroup>
+ </StyledSelectorContainer>
+ <StyledSelectorContainer>
<AriaInputGroup>
- <StyledSelectorContainer>
+ {this.props.openvpn.protocol ? (
<Selector
- title={
- // TRANSLATORS: The title for the shadowsocks bridge selector section.
- messages.pgettext('openvpn-settings-view', 'Bridge mode')
- }
- values={this.bridgeStateItems(
- this.props.bridgeModeAvailablity === BridgeModeAvailability.available,
+ title={sprintf(
+ // TRANSLATORS: The title for the port selector section.
+ // TRANSLATORS: Available placeholders:
+ // TRANSLATORS: %(portType)s - a selected protocol (either TCP or UDP)
+ messages.pgettext('openvpn-settings-view', '%(portType)s port'),
+ {
+ portType: this.props.openvpn.protocol.toUpperCase(),
+ },
)}
- value={this.props.bridgeState}
- onSelect={this.onSelectBridgeState}
- hasFooter
+ values={this.portItems[this.props.openvpn.protocol]}
+ value={this.props.openvpn.port}
+ onSelect={this.onSelectOpenVpnPort}
/>
- </StyledSelectorContainer>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>{this.bridgeModeFooterText()}</Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
+ ) : undefined}
</AriaInputGroup>
+ </StyledSelectorContainer>
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('openvpn-settings-view', 'Mssfix')}
- </Cell.InputLabel>
- </AriaLabel>
- <StyledInputFrame>
- <AriaInput>
- <Cell.AutoSizingTextInput
- value={this.props.mssfix ? this.props.mssfix.toString() : ''}
- inputMode={'numeric'}
- maxLength={4}
- placeholder={messages.gettext('Default')}
- onSubmitValue={this.onMssfixSubmit}
- validateValue={OpenVpnSettings.mssfixIsValid}
- submitOnBlur={true}
- modifyValue={OpenVpnSettings.removeNonNumericCharacters}
- />
- </AriaInput>
- </StyledInputFrame>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {sprintf(
- // TRANSLATORS: The hint displayed below the Mssfix input field.
- // TRANSLATORS: Available placeholders:
- // TRANSLATORS: %(max)d - the maximum possible mssfix value
- // TRANSLATORS: %(min)d - the minimum possible mssfix value
- messages.pgettext(
- 'openvpn-settings-view',
- 'Set OpenVPN MSS value. Valid range: %(min)d - %(max)d.',
- ),
- {
- min: MIN_MSSFIX_VALUE,
- max: MAX_MSSFIX_VALUE,
- },
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
- </StyledNavigationScrollbars>
- </NavigationContainer>
- </SettingsContainer>
- </Layout>
+ <AriaInputGroup>
+ <StyledSelectorContainer>
+ <Selector
+ title={
+ // TRANSLATORS: The title for the shadowsocks bridge selector section.
+ messages.pgettext('openvpn-settings-view', 'Bridge mode')
+ }
+ values={this.bridgeStateItems(
+ this.props.bridgeModeAvailablity === BridgeModeAvailability.available,
+ )}
+ value={this.props.bridgeState}
+ onSelect={this.onSelectBridgeState}
+ hasFooter
+ />
+ </StyledSelectorContainer>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>{this.bridgeModeFooterText()}</Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('openvpn-settings-view', 'Mssfix')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <StyledInputFrame>
+ <AriaInput>
+ <Cell.AutoSizingTextInput
+ value={this.props.mssfix ? this.props.mssfix.toString() : ''}
+ inputMode={'numeric'}
+ maxLength={4}
+ placeholder={messages.gettext('Default')}
+ onSubmitValue={this.onMssfixSubmit}
+ validateValue={OpenVpnSettings.mssfixIsValid}
+ submitOnBlur={true}
+ modifyValue={OpenVpnSettings.removeNonNumericCharacters}
+ />
+ </AriaInput>
+ </StyledInputFrame>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {sprintf(
+ // TRANSLATORS: The hint displayed below the Mssfix input field.
+ // TRANSLATORS: Available placeholders:
+ // TRANSLATORS: %(max)d - the maximum possible mssfix value
+ // TRANSLATORS: %(min)d - the minimum possible mssfix value
+ messages.pgettext(
+ 'openvpn-settings-view',
+ 'Set OpenVPN MSS value. Valid range: %(min)d - %(max)d.',
+ ),
+ {
+ min: MIN_MSSFIX_VALUE,
+ max: MAX_MSSFIX_VALUE,
+ },
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+ </StyledNavigationScrollbars>
+ </NavigationContainer>
+ </SettingsContainer>
{this.state.showBridgeStateConfirmationDialog && this.renderBridgeStateConfirmation()}
- </ModalContainer>
+ </Layout>
);
}
diff --git a/gui/src/renderer/components/Preferences.tsx b/gui/src/renderer/components/Preferences.tsx
index 7adcfcf3e4..46b5a54054 100644
--- a/gui/src/renderer/components/Preferences.tsx
+++ b/gui/src/renderer/components/Preferences.tsx
@@ -9,7 +9,7 @@ import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGro
import * as Cell from './cell';
import ImageView from './ImageView';
import { Layout } from './Layout';
-import { ModalAlert, ModalAlertType, ModalContainer } from './Modal';
+import { ModalAlert, ModalAlertType } from './Modal';
import {
BackBarItem,
NavigationBar,
@@ -53,204 +53,228 @@ export default class Preferences extends React.Component<IProps, IState> {
public render() {
return (
- <ModalContainer>
- <Layout>
- <StyledContainer>
- <NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <BackBarItem action={this.props.onClose}>
- {
- // TRANSLATORS: Back button in navigation bar
- messages.pgettext('navigation-bar', 'Settings')
- }
- </BackBarItem>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('preferences-nav', 'Preferences')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <Layout>
+ <StyledContainer>
+ <NavigationContainer>
+ <NavigationBar>
+ <NavigationItems>
+ <BackBarItem action={this.props.onClose}>
+ {
+ // TRANSLATORS: Back button in navigation bar
+ messages.pgettext('navigation-bar', 'Settings')
+ }
+ </BackBarItem>
+ <TitleBarItem>
+ {
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('preferences-nav', 'Preferences')
+ }
+ </TitleBarItem>
+ </NavigationItems>
+ </NavigationBar>
- <NavigationScrollbars>
- <SettingsHeader>
- <HeaderTitle>{messages.pgettext('preferences-view', 'Preferences')}</HeaderTitle>
- </SettingsHeader>
+ <NavigationScrollbars>
+ <SettingsHeader>
+ <HeaderTitle>{messages.pgettext('preferences-view', 'Preferences')}</HeaderTitle>
+ </SettingsHeader>
- <StyledContent>
- <Cell.CellButton onClick={this.showKillSwitchInfo}>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Kill switch')}
- </Cell.InputLabel>
- <ImageView source="icon-info" width={24} tintColor={colors.white} />
- </Cell.CellButton>
- <StyledSeparator height={20} />
+ <StyledContent>
+ <Cell.CellButton onClick={this.showKillSwitchInfo}>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Kill switch')}
+ </Cell.InputLabel>
+ <ImageView source="icon-info" width={24} tintColor={colors.white} />
+ </Cell.CellButton>
+ <StyledSeparator height={20} />
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Launch app on start-up')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={this.props.autoStart}
- onChange={this.props.setAutoStart}
- />
- </AriaInput>
- </Cell.Container>
- </AriaInputGroup>
- <StyledSeparator />
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Launch app on start-up')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch isOn={this.props.autoStart} onChange={this.props.setAutoStart} />
+ </AriaInput>
+ </Cell.Container>
+ </AriaInputGroup>
+ <StyledSeparator />
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Auto-connect')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={this.props.autoConnect}
- onChange={this.props.setAutoConnect}
- />
- </AriaInput>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {messages.pgettext(
- 'preferences-view',
- 'Automatically connect to a server when the app launches.',
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Auto-connect')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ isOn={this.props.autoConnect}
+ onChange={this.props.setAutoConnect}
+ />
+ </AriaInput>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {messages.pgettext(
+ 'preferences-view',
+ 'Automatically connect to a server when the app launches.',
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
- <AriaInputGroup>
- <Cell.Container disabled={this.props.dns.state === 'custom'}>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Block ads')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={
- this.props.dns.state === 'default' &&
- this.props.dns.defaultOptions.blockAds
- }
- onChange={this.setBlockAds}
- />
- </AriaInput>
- </Cell.Container>
- </AriaInputGroup>
- <StyledSeparator />
- <AriaInputGroup>
- <Cell.Container disabled={this.props.dns.state === 'custom'}>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Block trackers')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={
- this.props.dns.state === 'default' &&
- this.props.dns.defaultOptions.blockTrackers
- }
- onChange={this.setBlockTrackers}
- />
- </AriaInput>
- </Cell.Container>
- </AriaInputGroup>
- <StyledSeparator />
- <AriaInputGroup>
- <Cell.Container disabled={this.props.dns.state === 'custom'}>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Block malware')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={
- this.props.dns.state === 'default' &&
- this.props.dns.defaultOptions.blockMalware
- }
- onChange={this.setBlockMalware}
- />
- </AriaInput>
- </Cell.Container>
- {this.props.dns.state === 'custom' && <CustomDnsEnabledFooter />}
- </AriaInputGroup>
+ <AriaInputGroup>
+ <Cell.Container disabled={this.props.dns.state === 'custom'}>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Block ads')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ isOn={
+ this.props.dns.state === 'default' &&
+ this.props.dns.defaultOptions.blockAds
+ }
+ onChange={this.setBlockAds}
+ />
+ </AriaInput>
+ </Cell.Container>
+ </AriaInputGroup>
+ <StyledSeparator />
+ <AriaInputGroup>
+ <Cell.Container disabled={this.props.dns.state === 'custom'}>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Block trackers')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ isOn={
+ this.props.dns.state === 'default' &&
+ this.props.dns.defaultOptions.blockTrackers
+ }
+ onChange={this.setBlockTrackers}
+ />
+ </AriaInput>
+ </Cell.Container>
+ </AriaInputGroup>
+ <StyledSeparator />
+ <AriaInputGroup>
+ <Cell.Container disabled={this.props.dns.state === 'custom'}>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Block malware')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ isOn={
+ this.props.dns.state === 'default' &&
+ this.props.dns.defaultOptions.blockMalware
+ }
+ onChange={this.setBlockMalware}
+ />
+ </AriaInput>
+ </Cell.Container>
+ {this.props.dns.state === 'custom' && <CustomDnsEnabledFooter />}
+ </AriaInputGroup>
- {this.props.dns.state !== 'custom' && <StyledSeparator height={20} />}
+ {this.props.dns.state !== 'custom' && <StyledSeparator height={20} />}
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Local network sharing')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch isOn={this.props.allowLan} onChange={this.props.setAllowLan} />
- </AriaInput>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {messages.pgettext(
- 'preferences-view',
- 'Allows access to other devices on the same network for sharing, printing etc.',
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Local network sharing')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch isOn={this.props.allowLan} onChange={this.props.setAllowLan} />
+ </AriaInput>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {messages.pgettext(
+ 'preferences-view',
+ 'Allows access to other devices on the same network for sharing, printing etc.',
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Notifications')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={this.props.enableSystemNotifications}
- onChange={this.props.setEnableSystemNotifications}
- />
- </AriaInput>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {messages.pgettext(
- 'preferences-view',
- 'Enable or disable system notifications. The critical notifications will always be displayed.',
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Notifications')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ isOn={this.props.enableSystemNotifications}
+ onChange={this.props.setEnableSystemNotifications}
+ />
+ </AriaInput>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {messages.pgettext(
+ 'preferences-view',
+ 'Enable or disable system notifications. The critical notifications will always be displayed.',
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Monochromatic tray icon')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ isOn={this.props.monochromaticIcon}
+ onChange={this.props.setMonochromaticIcon}
+ />
+ </AriaInput>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {messages.pgettext(
+ 'preferences-view',
+ 'Use a monochromatic tray icon instead of a colored one.',
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+
+ {(window.env.platform === 'win32' ||
+ (window.env.platform === 'darwin' && window.env.development)) && (
<AriaInputGroup>
<Cell.Container>
<AriaLabel>
<Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Monochromatic tray icon')}
+ {messages.pgettext('preferences-view', 'Unpin app from taskbar')}
</Cell.InputLabel>
</AriaLabel>
<AriaInput>
<Cell.Switch
- isOn={this.props.monochromaticIcon}
- onChange={this.props.setMonochromaticIcon}
+ isOn={this.props.unpinnedWindow}
+ onChange={this.props.setUnpinnedWindow}
/>
</AriaInput>
</Cell.Container>
@@ -259,26 +283,27 @@ export default class Preferences extends React.Component<IProps, IState> {
<Cell.FooterText>
{messages.pgettext(
'preferences-view',
- 'Use a monochromatic tray icon instead of a colored one.',
+ 'Enable to move the app around as a free-standing window.',
)}
</Cell.FooterText>
</AriaDescription>
</Cell.Footer>
</AriaInputGroup>
+ )}
- {(window.env.platform === 'win32' ||
- (window.env.platform === 'darwin' && window.env.development)) && (
+ {this.props.unpinnedWindow && (
+ <React.Fragment>
<AriaInputGroup>
<Cell.Container>
<AriaLabel>
<Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Unpin app from taskbar')}
+ {messages.pgettext('preferences-view', 'Start minimized')}
</Cell.InputLabel>
</AriaLabel>
<AriaInput>
<Cell.Switch
- isOn={this.props.unpinnedWindow}
- onChange={this.props.setUnpinnedWindow}
+ isOn={this.props.startMinimized}
+ onChange={this.props.setStartMinimized}
/>
</AriaInput>
</Cell.Container>
@@ -287,79 +312,49 @@ export default class Preferences extends React.Component<IProps, IState> {
<Cell.FooterText>
{messages.pgettext(
'preferences-view',
- 'Enable to move the app around as a free-standing window.',
+ 'Show only the tray icon when the app starts.',
)}
</Cell.FooterText>
</AriaDescription>
</Cell.Footer>
</AriaInputGroup>
- )}
-
- {this.props.unpinnedWindow && (
- <React.Fragment>
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Start minimized')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={this.props.startMinimized}
- onChange={this.props.setStartMinimized}
- />
- </AriaInput>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {messages.pgettext(
- 'preferences-view',
- 'Show only the tray icon when the app starts.',
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
- </React.Fragment>
- )}
+ </React.Fragment>
+ )}
- <AriaInputGroup>
- <Cell.Container disabled={this.props.isBeta}>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('preferences-view', 'Beta program')}
- </Cell.InputLabel>
- </AriaLabel>
- <AriaInput>
- <Cell.Switch
- isOn={this.props.showBetaReleases}
- onChange={this.props.setShowBetaReleases}
- />
- </AriaInput>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {this.props.isBeta
- ? messages.pgettext(
- 'preferences-view',
- 'This option is unavailable while using a beta version.',
- )
- : messages.pgettext(
- 'preferences-view',
- 'Enable to get notified when new beta versions of the app are released.',
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
- </StyledContent>
- </NavigationScrollbars>
- </NavigationContainer>
- </StyledContainer>
- </Layout>
+ <AriaInputGroup>
+ <Cell.Container disabled={this.props.isBeta}>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('preferences-view', 'Beta program')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ isOn={this.props.showBetaReleases}
+ onChange={this.props.setShowBetaReleases}
+ />
+ </AriaInput>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {this.props.isBeta
+ ? messages.pgettext(
+ 'preferences-view',
+ 'This option is unavailable while using a beta version.',
+ )
+ : messages.pgettext(
+ 'preferences-view',
+ 'Enable to get notified when new beta versions of the app are released.',
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+ </StyledContent>
+ </NavigationScrollbars>
+ </NavigationContainer>
+ </StyledContainer>
{this.state.showKillSwitchInfo && (
<ModalAlert
@@ -376,7 +371,7 @@ export default class Preferences extends React.Component<IProps, IState> {
close={this.hideKillSwitchInfo}
/>
)}
- </ModalContainer>
+ </Layout>
);
}
diff --git a/gui/src/renderer/components/SplitTunnelingSettings.tsx b/gui/src/renderer/components/SplitTunnelingSettings.tsx
index 5f6f125d39..a0ea98bcd9 100644
--- a/gui/src/renderer/components/SplitTunnelingSettings.tsx
+++ b/gui/src/renderer/components/SplitTunnelingSettings.tsx
@@ -15,7 +15,7 @@ import { CustomScrollbarsRef } from './CustomScrollbars';
import ImageView from './ImageView';
import { Layout } from './Layout';
import List from './List';
-import { ModalContainer, ModalAlert, ModalAlertType } from './Modal';
+import { ModalAlert, ModalAlertType } from './Modal';
import {
BackBarItem,
NavigationBar,
@@ -59,39 +59,37 @@ export default function SplitTunneling() {
return (
<>
<StyledPageCover show={browsing} />
- <ModalContainer>
- <Layout>
- <StyledContainer>
- <NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <BackBarItem action={pop}>
- {
- // TRANSLATORS: Back button in navigation bar
- messages.pgettext('navigation-bar', 'Advanced')
- }
- </BackBarItem>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('split-tunneling-nav', 'Split tunneling')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <Layout>
+ <StyledContainer>
+ <NavigationContainer>
+ <NavigationBar>
+ <NavigationItems>
+ <BackBarItem action={pop}>
+ {
+ // TRANSLATORS: Back button in navigation bar
+ messages.pgettext('navigation-bar', 'Advanced')
+ }
+ </BackBarItem>
+ <TitleBarItem>
+ {
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('split-tunneling-nav', 'Split tunneling')
+ }
+ </TitleBarItem>
+ </NavigationItems>
+ </NavigationBar>
- <StyledNavigationScrollbars ref={scrollbarsRef}>
- <StyledContent>
- <PlatformSpecificSplitTunnelingSettings
- setBrowsing={setBrowsing}
- scrollToTop={scrollToTop}
- />
- </StyledContent>
- </StyledNavigationScrollbars>
- </NavigationContainer>
- </StyledContainer>
- </Layout>
- </ModalContainer>
+ <StyledNavigationScrollbars ref={scrollbarsRef}>
+ <StyledContent>
+ <PlatformSpecificSplitTunnelingSettings
+ setBrowsing={setBrowsing}
+ scrollToTop={scrollToTop}
+ />
+ </StyledContent>
+ </StyledNavigationScrollbars>
+ </NavigationContainer>
+ </StyledContainer>
+ </Layout>
</>
);
}
diff --git a/gui/src/renderer/components/Support.tsx b/gui/src/renderer/components/Support.tsx
index d34e6b6b08..eaea64d789 100644
--- a/gui/src/renderer/components/Support.tsx
+++ b/gui/src/renderer/components/Support.tsx
@@ -5,7 +5,7 @@ import * as AppButton from './AppButton';
import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGroup';
import ImageView from './ImageView';
import { Layout } from './Layout';
-import { ModalAlert, ModalAlertType, ModalContainer } from './Modal';
+import { ModalAlert, ModalAlertType } from './Modal';
import { BackBarItem, NavigationBar, NavigationItems, TitleBarItem } from './NavigationBar';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
import {
@@ -150,35 +150,33 @@ export default class Support extends React.Component<ISupportProps, ISupportStat
const content = this.renderContent();
return (
- <ModalContainer>
- <Layout>
- <StyledContainer>
- <NavigationBar>
- <NavigationItems>
- <BackBarItem action={this.props.onClose}>
- {
- // TRANSLATORS: Back button in navigation bar
- messages.pgettext('navigation-bar', 'Settings')
- }
- </BackBarItem>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('support-view', 'Report a problem')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
- <StyledContentContainer>
- {header}
- {content}
- </StyledContentContainer>
+ <Layout>
+ <StyledContainer>
+ <NavigationBar>
+ <NavigationItems>
+ <BackBarItem action={this.props.onClose}>
+ {
+ // TRANSLATORS: Back button in navigation bar
+ messages.pgettext('navigation-bar', 'Settings')
+ }
+ </BackBarItem>
+ <TitleBarItem>
+ {
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('support-view', 'Report a problem')
+ }
+ </TitleBarItem>
+ </NavigationItems>
+ </NavigationBar>
+ <StyledContentContainer>
+ {header}
+ {content}
+ </StyledContentContainer>
- {sendState === SendState.confirm && this.renderNoEmailDialog()}
- {showOutdatedVersionWarning && this.renderOutdateVersionWarningDialog()}
- </StyledContainer>
- </Layout>
- </ModalContainer>
+ {sendState === SendState.confirm && this.renderNoEmailDialog()}
+ {showOutdatedVersionWarning && this.renderOutdateVersionWarningDialog()}
+ </StyledContainer>
+ </Layout>
);
}
diff --git a/gui/src/renderer/components/WireguardSettings.tsx b/gui/src/renderer/components/WireguardSettings.tsx
index 6a90c307f8..8d5d47f38c 100644
--- a/gui/src/renderer/components/WireguardSettings.tsx
+++ b/gui/src/renderer/components/WireguardSettings.tsx
@@ -7,7 +7,7 @@ import * as AppButton from './AppButton';
import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup';
import * as Cell from './cell';
import { Layout, SettingsContainer } from './Layout';
-import { ModalAlert, ModalAlertType, ModalContainer } from './Modal';
+import { ModalAlert, ModalAlertType } from './Modal';
import {
BackBarItem,
NavigationBar,
@@ -101,176 +101,174 @@ export default class WireguardSettings extends React.Component<IProps, IState> {
public render() {
return (
- <ModalContainer>
- <Layout>
- <SettingsContainer>
- <NavigationContainer>
- <NavigationBar>
- <NavigationItems>
- <BackBarItem action={this.props.onClose}>
- {
- // TRANSLATORS: Back button in navigation bar
- messages.pgettext('navigation-bar', 'Advanced')
- }
- </BackBarItem>
- <TitleBarItem>
- {
- // TRANSLATORS: Title label in navigation bar
- messages.pgettext('wireguard-settings-nav', 'WireGuard settings')
- }
- </TitleBarItem>
- </NavigationItems>
- </NavigationBar>
+ <Layout>
+ <SettingsContainer>
+ <NavigationContainer>
+ <NavigationBar>
+ <NavigationItems>
+ <BackBarItem action={this.props.onClose}>
+ {
+ // TRANSLATORS: Back button in navigation bar
+ messages.pgettext('navigation-bar', 'Advanced')
+ }
+ </BackBarItem>
+ <TitleBarItem>
+ {
+ // TRANSLATORS: Title label in navigation bar
+ messages.pgettext('wireguard-settings-nav', 'WireGuard settings')
+ }
+ </TitleBarItem>
+ </NavigationItems>
+ </NavigationBar>
- <StyledNavigationScrollbars>
- <SettingsHeader>
- <HeaderTitle>
- {messages.pgettext('wireguard-settings-view', 'WireGuard settings')}
- </HeaderTitle>
- </SettingsHeader>
+ <StyledNavigationScrollbars>
+ <SettingsHeader>
+ <HeaderTitle>
+ {messages.pgettext('wireguard-settings-view', 'WireGuard settings')}
+ </HeaderTitle>
+ </SettingsHeader>
- <AriaInputGroup>
- <StyledSelectorContainer>
- <StyledSelectorForFooter
- // TRANSLATORS: The title for the WireGuard port selector.
- title={messages.pgettext('wireguard-settings-view', 'Port')}
- values={this.wireguardPortItems}
- value={this.props.wireguard.port}
- onSelect={this.props.setWireguardPort}
+ <AriaInputGroup>
+ <StyledSelectorContainer>
+ <StyledSelectorForFooter
+ // TRANSLATORS: The title for the WireGuard port selector.
+ title={messages.pgettext('wireguard-settings-view', 'Port')}
+ values={this.wireguardPortItems}
+ value={this.props.wireguard.port}
+ onSelect={this.props.setWireguardPort}
+ />
+ </StyledSelectorContainer>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {
+ // TRANSLATORS: The hint displayed below the WireGuard port selector.
+ messages.pgettext(
+ 'wireguard-settings-view',
+ 'The automatic setting will randomly choose from a wide range of ports.',
+ )
+ }
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {
+ // TRANSLATORS: The label next to the multihop settings toggle.
+ messages.pgettext('advanced-settings-view', 'Enable multihop')
+ }
+ </Cell.InputLabel>
+ </AriaLabel>
+ <AriaInput>
+ <Cell.Switch
+ ref={this.multihopRef}
+ isOn={this.props.wireguardMultihop}
+ onChange={this.setWireguardMultihop}
/>
- </StyledSelectorContainer>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {
- // TRANSLATORS: The hint displayed below the WireGuard port selector.
- messages.pgettext(
- 'wireguard-settings-view',
- 'The automatic setting will randomly choose from a wide range of ports.',
- )
- }
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
+ </AriaInput>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {
+ // TRANSLATORS: Description for multihop settings toggle.
+ messages.pgettext(
+ 'advanced-settings-view',
+ 'Increases anonymity by routing your traffic into one WireGuard server and out another, making it harder to trace.',
+ )
+ }
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {
- // TRANSLATORS: The label next to the multihop settings toggle.
- messages.pgettext('advanced-settings-view', 'Enable multihop')
- }
- </Cell.InputLabel>
- </AriaLabel>
+ <AriaInputGroup>
+ <StyledSelectorContainer>
+ <StyledSelectorForFooter
+ // TRANSLATORS: The title for the WireGuard IP version selector.
+ title={messages.pgettext('wireguard-settings-view', 'IP version')}
+ values={this.wireguardIpVersionItems}
+ value={this.props.wireguard.ipVersion}
+ onSelect={this.props.setWireguardIpVersion}
+ />
+ </StyledSelectorContainer>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {
+ // TRANSLATORS: The hint displayed below the WireGuard IP version selector.
+ messages.pgettext(
+ 'wireguard-settings-view',
+ 'This allows access to WireGuard for devices that only support IPv6.',
+ )
+ }
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+
+ <Cell.CellButtonGroup>
+ <Cell.CellButton onClick={this.props.onViewWireguardKeys}>
+ <Cell.Label>
+ {messages.pgettext('wireguard-settings-view', 'WireGuard key')}
+ </Cell.Label>
+ <Cell.Icon height={12} width={7} source="icon-chevron" />
+ </Cell.CellButton>
+ </Cell.CellButtonGroup>
+
+ <AriaInputGroup>
+ <Cell.Container>
+ <AriaLabel>
+ <Cell.InputLabel>
+ {messages.pgettext('wireguard-settings-view', 'MTU')}
+ </Cell.InputLabel>
+ </AriaLabel>
+ <StyledInputFrame>
<AriaInput>
- <Cell.Switch
- ref={this.multihopRef}
- isOn={this.props.wireguardMultihop}
- onChange={this.setWireguardMultihop}
+ <Cell.AutoSizingTextInput
+ value={this.props.wireguardMtu ? this.props.wireguardMtu.toString() : ''}
+ inputMode={'numeric'}
+ maxLength={4}
+ placeholder={messages.gettext('Default')}
+ onSubmitValue={this.onWireguardMtuSubmit}
+ validateValue={WireguardSettings.wireguarMtuIsValid}
+ submitOnBlur={true}
+ modifyValue={WireguardSettings.removeNonNumericCharacters}
/>
</AriaInput>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
+ </StyledInputFrame>
+ </Cell.Container>
+ <Cell.Footer>
+ <AriaDescription>
+ <Cell.FooterText>
+ {sprintf(
+ // TRANSLATORS: The hint displayed below the WireGuard MTU input field.
+ // TRANSLATORS: Available placeholders:
+ // TRANSLATORS: %(max)d - the maximum possible wireguard mtu value
+ // TRANSLATORS: %(min)d - the minimum possible wireguard mtu value
+ messages.pgettext(
+ 'wireguard-settings-view',
+ 'Set WireGuard MTU value. Valid range: %(min)d - %(max)d.',
+ ),
{
- // TRANSLATORS: Description for multihop settings toggle.
- messages.pgettext(
- 'advanced-settings-view',
- 'Increases anonymity by routing your traffic into one WireGuard server and out another, making it harder to trace.',
- )
- }
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
-
- <AriaInputGroup>
- <StyledSelectorContainer>
- <StyledSelectorForFooter
- // TRANSLATORS: The title for the WireGuard IP version selector.
- title={messages.pgettext('wireguard-settings-view', 'IP version')}
- values={this.wireguardIpVersionItems}
- value={this.props.wireguard.ipVersion}
- onSelect={this.props.setWireguardIpVersion}
- />
- </StyledSelectorContainer>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {
- // TRANSLATORS: The hint displayed below the WireGuard IP version selector.
- messages.pgettext(
- 'wireguard-settings-view',
- 'This allows access to WireGuard for devices that only support IPv6.',
- )
- }
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
-
- <Cell.CellButtonGroup>
- <Cell.CellButton onClick={this.props.onViewWireguardKeys}>
- <Cell.Label>
- {messages.pgettext('wireguard-settings-view', 'WireGuard key')}
- </Cell.Label>
- <Cell.Icon height={12} width={7} source="icon-chevron" />
- </Cell.CellButton>
- </Cell.CellButtonGroup>
-
- <AriaInputGroup>
- <Cell.Container>
- <AriaLabel>
- <Cell.InputLabel>
- {messages.pgettext('wireguard-settings-view', 'MTU')}
- </Cell.InputLabel>
- </AriaLabel>
- <StyledInputFrame>
- <AriaInput>
- <Cell.AutoSizingTextInput
- value={this.props.wireguardMtu ? this.props.wireguardMtu.toString() : ''}
- inputMode={'numeric'}
- maxLength={4}
- placeholder={messages.gettext('Default')}
- onSubmitValue={this.onWireguardMtuSubmit}
- validateValue={WireguardSettings.wireguarMtuIsValid}
- submitOnBlur={true}
- modifyValue={WireguardSettings.removeNonNumericCharacters}
- />
- </AriaInput>
- </StyledInputFrame>
- </Cell.Container>
- <Cell.Footer>
- <AriaDescription>
- <Cell.FooterText>
- {sprintf(
- // TRANSLATORS: The hint displayed below the WireGuard MTU input field.
- // TRANSLATORS: Available placeholders:
- // TRANSLATORS: %(max)d - the maximum possible wireguard mtu value
- // TRANSLATORS: %(min)d - the minimum possible wireguard mtu value
- messages.pgettext(
- 'wireguard-settings-view',
- 'Set WireGuard MTU value. Valid range: %(min)d - %(max)d.',
- ),
- {
- min: MIN_WIREGUARD_MTU_VALUE,
- max: MAX_WIREGUARD_MTU_VALUE,
- },
- )}
- </Cell.FooterText>
- </AriaDescription>
- </Cell.Footer>
- </AriaInputGroup>
- </StyledNavigationScrollbars>
- </NavigationContainer>
- </SettingsContainer>
- </Layout>
+ min: MIN_WIREGUARD_MTU_VALUE,
+ max: MAX_WIREGUARD_MTU_VALUE,
+ },
+ )}
+ </Cell.FooterText>
+ </AriaDescription>
+ </Cell.Footer>
+ </AriaInputGroup>
+ </StyledNavigationScrollbars>
+ </NavigationContainer>
+ </SettingsContainer>
{this.state.showMultihopConfirmationDialog && this.renderMultihopConfirmation()}
- </ModalContainer>
+ </Layout>
);
}