diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-01-18 21:19:39 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-01-27 10:39:37 +0100 |
| commit | 270a9fbc30a79e60283349274684e6eb6d5ff523 (patch) | |
| tree | a18a54c7853f161d178e42e22420834a30bd7277 /gui/src | |
| parent | bc7ebf12c08b0fa9a0d8ec2ec9db026b24a57080 (diff) | |
| download | mullvadvpn-270a9fbc30a79e60283349274684e6eb6d5ff523.tar.xz mullvadvpn-270a9fbc30a79e60283349274684e6eb6d5ff523.zip | |
Wrap entire app in ModalContainer
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/renderer/app.tsx | 14 | ||||
| -rw-r--r-- | gui/src/renderer/components/Account.tsx | 141 | ||||
| -rw-r--r-- | gui/src/renderer/components/AdvancedSettings.tsx | 253 | ||||
| -rw-r--r-- | gui/src/renderer/components/AppRouter.tsx | 73 | ||||
| -rw-r--r-- | gui/src/renderer/components/Connect.tsx | 11 | ||||
| -rw-r--r-- | gui/src/renderer/components/ErrorBoundary.tsx | 7 | ||||
| -rw-r--r-- | gui/src/renderer/components/ExpiredAccountErrorView.tsx | 48 | ||||
| -rw-r--r-- | gui/src/renderer/components/OpenVPNSettings.tsx | 276 | ||||
| -rw-r--r-- | gui/src/renderer/components/Preferences.tsx | 507 | ||||
| -rw-r--r-- | gui/src/renderer/components/SplitTunnelingSettings.tsx | 64 | ||||
| -rw-r--r-- | gui/src/renderer/components/Support.tsx | 56 | ||||
| -rw-r--r-- | gui/src/renderer/components/WireguardSettings.tsx | 320 |
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> ); } |
