diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2021-05-20 10:19:10 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2021-05-21 10:38:59 +0200 |
| commit | 5a8a3fc7f615ab13fe38e28908a9b09383bff086 (patch) | |
| tree | cd8f6a13afba068d41d9b9738c18cf87fda68ddf /gui/src/renderer/components | |
| parent | 25fe65cea4876a780ddf87da0576802951d32eff (diff) | |
| download | mullvadvpn-5a8a3fc7f615ab13fe38e28908a9b09383bff086.tar.xz mullvadvpn-5a8a3fc7f615ab13fe38e28908a9b09383bff086.zip | |
Add ad/tracker blocking settings to desktop app
Diffstat (limited to 'gui/src/renderer/components')
| -rw-r--r-- | gui/src/renderer/components/AdvancedSettings.tsx | 81 | ||||
| -rw-r--r-- | gui/src/renderer/components/Preferences.tsx | 90 | ||||
| -rw-r--r-- | gui/src/renderer/components/PreferencesStyles.tsx | 6 |
3 files changed, 158 insertions, 19 deletions
diff --git a/gui/src/renderer/components/AdvancedSettings.tsx b/gui/src/renderer/components/AdvancedSettings.tsx index a81981263a..ef59798a46 100644 --- a/gui/src/renderer/components/AdvancedSettings.tsx +++ b/gui/src/renderer/components/AdvancedSettings.tsx @@ -42,6 +42,7 @@ import { import Selector, { ISelectorItem } from './cell/Selector'; import SettingsHeader, { HeaderTitle } from './SettingsHeader'; import Accordion from './Accordion'; +import { formatMarkdown } from '../markdown-formatter'; const MIN_MSSFIX_VALUE = 1000; const MAX_MSSFIX_VALUE = 1450; @@ -448,7 +449,7 @@ export default class AdvancedSettings extends React.Component<IProps, IState> { )} </StyledButtonCellGroup> - <StyledCustomDnsSwitchContainer> + <StyledCustomDnsSwitchContainer disabled={!this.customDnsAvailable()}> <AriaInputGroup> <AriaLabel> <Cell.InputLabel> @@ -458,13 +459,17 @@ export default class AdvancedSettings extends React.Component<IProps, IState> { <AriaInput> <Cell.Switch ref={this.customDnsSwitchRef} - isOn={this.props.dns.custom || this.state.showAddCustomDns} + isOn={this.props.dns.state === 'custom' || this.state.showAddCustomDns} onChange={this.setCustomDnsEnabled} /> </AriaInput> </AriaInputGroup> </StyledCustomDnsSwitchContainer> - <Accordion expanded={this.props.dns.custom || this.state.showAddCustomDns}> + <Accordion + expanded={ + this.customDnsAvailable() && + (this.props.dns.state === 'custom' || this.state.showAddCustomDns) + }> <CellList items={this.customDnsItems()} onRemove={this.removeDnsAddress} /> {this.state.showAddCustomDns && ( @@ -502,9 +507,13 @@ export default class AdvancedSettings extends React.Component<IProps, IState> { <StyledCustomDnsFotter> <Cell.FooterText> - {messages.pgettext( - 'advanced-settings-view', - 'Enable to add at least one DNS server.', + {this.customDnsAvailable() ? ( + messages.pgettext( + 'advanced-settings-view', + 'Enable to add at least one DNS server.', + ) + ) : ( + <CustomDnsDisabledMessage /> )} </Cell.FooterText> </StyledCustomDnsFotter> @@ -520,15 +529,22 @@ export default class AdvancedSettings extends React.Component<IProps, IState> { ); } + private customDnsAvailable(): boolean { + return ( + this.props.dns.state === 'custom' || + (!this.props.dns.defaultOptions.blockAds && !this.props.dns.defaultOptions.blockTrackers) + ); + } + private setCustomDnsEnabled = async (enabled: boolean) => { - if (this.props.dns.addresses.length > 0) { + if (this.props.dns.customOptions.addresses.length > 0) { await this.props.setDnsOptions({ - custom: enabled, - addresses: this.props.dns.addresses, + ...this.props.dns, + state: enabled ? 'custom' : 'default', }); } - if (enabled && this.props.dns.addresses.length === 0) { + if (enabled && this.props.dns.customOptions.addresses.length === 0) { this.showAddCustomDnsRow(); } @@ -538,7 +554,7 @@ export default class AdvancedSettings extends React.Component<IProps, IState> { }; private customDnsItems(): ICellListItem<string>[] { - return this.props.dns.addresses.map((address) => ({ + return this.props.dns.customOptions.addresses.map((address) => ({ label: address, value: address, })); @@ -589,8 +605,12 @@ export default class AdvancedSettings extends React.Component<IProps, IState> { if (ipAddress.isLocal() || confirmed) { await this.props.setDnsOptions({ - custom: this.props.dns.custom || this.state.showAddCustomDns, - addresses: [...this.props.dns.addresses, address], + ...this.props.dns, + state: + this.props.dns.state === 'custom' || this.state.showAddCustomDns ? 'custom' : 'default', + customOptions: { + addresses: [...this.props.dns.customOptions.addresses, address], + }, }); this.hideAddCustomDnsRow(); } else { @@ -602,11 +622,14 @@ export default class AdvancedSettings extends React.Component<IProps, IState> { }; private removeDnsAddress = (address: string) => { - const addresses = this.props.dns.addresses.filter((item) => item !== address); + const addresses = this.props.dns.customOptions.addresses.filter((item) => item !== address); consumePromise( this.props.setDnsOptions({ - custom: addresses.length > 0 && this.props.dns.custom, - addresses, + ...this.props.dns, + state: addresses.length > 0 && this.props.dns.state === 'custom' ? 'custom' : 'default', + customOptions: { + addresses, + }, }), ); }; @@ -758,3 +781,29 @@ export default class AdvancedSettings extends React.Component<IProps, IState> { ); } } + +function CustomDnsDisabledMessage() { + const blockAdsFeatureName = messages.pgettext('preferences-view', 'Block ads'); + const blockTrackersFeatureName = messages.pgettext('preferences-view', 'Block trackers'); + const preferencesPageName = messages.pgettext('preferences-nav', 'Preferences'); + + // TRANSLATORS: This is displayed when either or both of the block ads/trackers settings are + // TRANSLATORS: turned on which makes the custom DNS setting disabled. The text enclosed in "**" + // TRANSLATORS: will appear bold. + // TRANSLATORS: Available placeholders: + // TRANSLATORS: %(blockAdsFeatureName)s - The name displayed next to the "Block ads" toggle. + // TRANSLATORS: %(blockTrackersFeatureName)s - The name displayed next to the "Block trackers" toggle. + // TRANSLATORS: %(preferencesPageName)s - The page title showed on top in the preferences page. + const customDnsDisabledMessage = messages.pgettext( + 'preferences-view', + 'Disable **%(blockAdsFeatureName)s** and **%(blockTrackersFeatureName)s** (under %(preferencesPageName)s) to activate this setting.', + ); + + return formatMarkdown( + sprintf(customDnsDisabledMessage, { + blockAdsFeatureName, + blockTrackersFeatureName, + preferencesPageName, + }), + ); +} diff --git a/gui/src/renderer/components/Preferences.tsx b/gui/src/renderer/components/Preferences.tsx index d47a7315c6..c91330aee0 100644 --- a/gui/src/renderer/components/Preferences.tsx +++ b/gui/src/renderer/components/Preferences.tsx @@ -1,5 +1,8 @@ import * as React from 'react'; +import { sprintf } from 'sprintf-js'; +import { IDnsOptions } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; +import { formatMarkdown } from '../markdown-formatter'; import { AriaDescription, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup'; import * as Cell from './cell'; import { Layout } from './Layout'; @@ -24,6 +27,7 @@ export interface IProps { monochromaticIcon: boolean; startMinimized: boolean; unpinnedWindow: boolean; + dns: IDnsOptions; setAutoStart: (autoStart: boolean) => void; setEnableSystemNotifications: (flag: boolean) => void; setAutoConnect: (autoConnect: boolean) => void; @@ -32,6 +36,7 @@ export interface IProps { setStartMinimized: (startMinimized: boolean) => void; setMonochromaticIcon: (monochromaticIcon: boolean) => void; setUnpinnedWindow: (unpinnedWindow: boolean) => void; + setDnsOptions: (dns: IDnsOptions) => Promise<void>; onClose: () => void; } @@ -105,6 +110,47 @@ export default class Preferences extends React.Component<IProps> { </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> + {this.props.dns.state === 'custom' && <CustomDnsEnabledFooter />} + </AriaInputGroup> + + {this.props.dns.state !== 'custom' && <StyledSeparator height={20} />} + + <AriaInputGroup> <Cell.Container> <AriaLabel> <Cell.InputLabel> @@ -275,4 +321,48 @@ export default class Preferences extends React.Component<IProps> { </Layout> ); } + + private setBlockAds = async (enabled: boolean) => { + await this.props.setDnsOptions({ + ...this.props.dns, + defaultOptions: { + ...this.props.dns.defaultOptions, + blockAds: enabled, + }, + }); + }; + + private setBlockTrackers = async (enabled: boolean) => { + await this.props.setDnsOptions({ + ...this.props.dns, + defaultOptions: { + ...this.props.dns.defaultOptions, + blockTrackers: enabled, + }, + }); + }; +} + +function CustomDnsEnabledFooter() { + const customDnsFeatureName = messages.pgettext('advanced-settings-view', 'Use custom DNS server'); + + // TRANSLATORS: This is displayed when the custom DNS setting is turned on which makes the block + // TRANSLATORS: ads/trackers settings disabled. The text enclosed in "**" will appear bold. + // TRANSLATORS: Advanced settings refer to the name of the page with the title "Advanced". + // TRANSLATORS: Available placeholders: + // TRANSLATORS: %(customDnsFeatureName)s - The name displayed next to the custom DNS toggle. + const blockingDisabledText = messages.pgettext( + 'preferences-view', + 'Disable **%(customDnsFeatureName)s** (under Advanced settings) to activate these settings.', + ); + + return ( + <Cell.Footer> + <AriaDescription> + <Cell.FooterText> + {formatMarkdown(sprintf(blockingDisabledText, { customDnsFeatureName }))} + </Cell.FooterText> + </AriaDescription> + </Cell.Footer> + ); } diff --git a/gui/src/renderer/components/PreferencesStyles.tsx b/gui/src/renderer/components/PreferencesStyles.tsx index b9986f2c38..f4fa114469 100644 --- a/gui/src/renderer/components/PreferencesStyles.tsx +++ b/gui/src/renderer/components/PreferencesStyles.tsx @@ -13,6 +13,6 @@ export const StyledContent = styled.div({ marginBottom: '2px', }); -export const StyledSeparator = styled.div({ - height: '1px', -}); +export const StyledSeparator = styled.div((props: { height?: number }) => ({ + height: `${props.height ?? 1}px`, +})); |
