diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2021-12-09 10:48:18 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2021-12-21 13:49:06 +0100 |
| commit | 7494a629bc466d2a4ea038bd30163f467ef6bfd0 (patch) | |
| tree | a29c07bae048c1b80cae050d45e3418c8f029548 /gui/src/renderer | |
| parent | c25d46683d5196597601f698285cc280da9806b2 (diff) | |
| download | mullvadvpn-7494a629bc466d2a4ea038bd30163f467ef6bfd0.tar.xz mullvadvpn-7494a629bc466d2a4ea038bd30163f467ef6bfd0.zip | |
Add kill switch information dialog
Diffstat (limited to 'gui/src/renderer')
| -rw-r--r-- | gui/src/renderer/components/Preferences.tsx | 495 |
1 files changed, 271 insertions, 224 deletions
diff --git a/gui/src/renderer/components/Preferences.tsx b/gui/src/renderer/components/Preferences.tsx index ebaa2da359..4f66b60d4a 100644 --- a/gui/src/renderer/components/Preferences.tsx +++ b/gui/src/renderer/components/Preferences.tsx @@ -1,11 +1,15 @@ import * as React from 'react'; import { sprintf } from 'sprintf-js'; +import { colors } from '../../config.json'; import { IDnsOptions } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; import { formatMarkdown } from '../markdown-formatter'; +import * as AppButton from './AppButton'; import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup'; import * as Cell from './cell'; +import ImageView from './ImageView'; import { Layout } from './Layout'; +import { ModalAlert, ModalAlertType, ModalContainer } from './Modal'; import { BackBarItem, NavigationBar, @@ -40,204 +44,194 @@ export interface IProps { onClose: () => void; } -export default class Preferences extends React.Component<IProps> { +interface IState { + showKillSwitchInfo: boolean; +} + +export default class Preferences extends React.Component<IProps, IState> { + public state = { showKillSwitchInfo: false }; + public render() { return ( - <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> + <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> - <NavigationScrollbars> - <SettingsHeader> - <HeaderTitle>{messages.pgettext('preferences-view', 'Preferences')}</HeaderTitle> - </SettingsHeader> + <NavigationScrollbars> + <SettingsHeader> + <HeaderTitle>{messages.pgettext('preferences-view', 'Preferences')}</HeaderTitle> + </SettingsHeader> - <StyledContent> - <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 /> + <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', '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', '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 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> - {this.props.dns.state === 'custom' && <CustomDnsEnabledFooter />} - </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> - {this.props.dns.state !== 'custom' && <StyledSeparator height={20} />} + <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> + {this.props.dns.state === 'custom' && <CustomDnsEnabledFooter />} + </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> + {this.props.dns.state !== 'custom' && <StyledSeparator height={20} />} - <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', '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', '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> + <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> - {(window.env.platform === 'win32' || - (window.env.platform === 'darwin' && window.env.development)) && ( <AriaInputGroup> <Cell.Container> <AriaLabel> <Cell.InputLabel> - {messages.pgettext('preferences-view', 'Unpin app from taskbar')} + {messages.pgettext('preferences-view', 'Monochromatic tray icon')} </Cell.InputLabel> </AriaLabel> <AriaInput> <Cell.Switch - isOn={this.props.unpinnedWindow} - onChange={this.props.setUnpinnedWindow} + isOn={this.props.monochromaticIcon} + onChange={this.props.setMonochromaticIcon} /> </AriaInput> </Cell.Container> @@ -246,27 +240,26 @@ export default class Preferences extends React.Component<IProps> { <Cell.FooterText> {messages.pgettext( 'preferences-view', - 'Enable to move the app around as a free-standing window.', + 'Use a monochromatic tray icon instead of a colored one.', )} </Cell.FooterText> </AriaDescription> </Cell.Footer> </AriaInputGroup> - )} - {this.props.unpinnedWindow && ( - <React.Fragment> + {(window.env.platform === 'win32' || + (window.env.platform === 'darwin' && window.env.development)) && ( <AriaInputGroup> <Cell.Container> <AriaLabel> <Cell.InputLabel> - {messages.pgettext('preferences-view', 'Start minimized')} + {messages.pgettext('preferences-view', 'Unpin app from taskbar')} </Cell.InputLabel> </AriaLabel> <AriaInput> <Cell.Switch - isOn={this.props.startMinimized} - onChange={this.props.setStartMinimized} + isOn={this.props.unpinnedWindow} + onChange={this.props.setUnpinnedWindow} /> </AriaInput> </Cell.Container> @@ -275,50 +268,96 @@ export default class Preferences extends React.Component<IProps> { <Cell.FooterText> {messages.pgettext( 'preferences-view', - 'Show only the tray icon when the app starts.', + 'Enable to move the app around as a free-standing window.', )} </Cell.FooterText> </AriaDescription> </Cell.Footer> </AriaInputGroup> - </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> + {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> + )} + + <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> + + {this.state.showKillSwitchInfo && ( + <ModalAlert + message={messages.pgettext( + 'preferences-view', + 'The app has a built in kill switch that is enabled by default and cannot be disabled. This is to prevent your traffic from leaking outside of the VPN tunnel if your network suddenly stops working or if the tunnel fails for any reason. Mullvad automatically protects your data until your connection is reestablished.', + )} + type={ModalAlertType.info} + buttons={[ + <AppButton.BlueButton key="back" onClick={this.hideKillSwitchInfo}> + {messages.gettext('Got it!')} + </AppButton.BlueButton>, + ]} + close={this.hideKillSwitchInfo} + /> + )} + </ModalContainer> ); } @@ -341,6 +380,14 @@ export default class Preferences extends React.Component<IProps> { }, }); }; + + private showKillSwitchInfo = () => { + this.setState({ showKillSwitchInfo: true }); + }; + + private hideKillSwitchInfo = () => { + this.setState({ showKillSwitchInfo: false }); + }; } function CustomDnsEnabledFooter() { |
