diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-05-05 11:14:37 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-05-05 11:14:37 +0200 |
| commit | 3a19900e51ca874e8202bfbd2853662a0652863e (patch) | |
| tree | c938ddc4471c35a1067212ec83f2a66c42cacebc | |
| parent | 7325107e01d8ff4c9cd405de36ccaa254d4e40c8 (diff) | |
| parent | e6fd227d8e788e5d89c3fae10791626c706daf4b (diff) | |
| download | mullvadvpn-3a19900e51ca874e8202bfbd2853662a0652863e.tar.xz mullvadvpn-3a19900e51ca874e8202bfbd2853662a0652863e.zip | |
Merge branch 'add-block-setting-info'
| -rw-r--r-- | gui/locales/messages.pot | 32 | ||||
| -rw-r--r-- | gui/src/renderer/components/AriaGroup.tsx | 13 | ||||
| -rw-r--r-- | gui/src/renderer/components/InfoButton.tsx | 65 | ||||
| -rw-r--r-- | gui/src/renderer/components/Preferences.tsx | 93 | ||||
| -rw-r--r-- | gui/src/renderer/components/PreferencesStyles.tsx | 5 |
5 files changed, 198 insertions, 10 deletions
diff --git a/gui/locales/messages.pot b/gui/locales/messages.pot index 19d93bd497..d741ac8e37 100644 --- a/gui/locales/messages.pot +++ b/gui/locales/messages.pot @@ -231,6 +231,10 @@ msgid "Login" msgstr "" msgctxt "accessibility" +msgid "More information" +msgstr "" + +msgctxt "accessibility" msgid "Opens externally" msgstr "" @@ -1062,6 +1066,34 @@ msgctxt "preferences-view" msgid "Use a monochromatic tray icon instead of a colored one." msgstr "" +msgctxt "preferences-view" +msgid "Warning: This is not an anti-virus and should not be treated as such, this is just an extra layer of protection." +msgstr "" + +msgctxt "preferences-view" +msgid "Warning: This might cause issues on certain websites, services, and programs." +msgstr "" + +msgctxt "preferences-view" +msgid "When enabled, this feature stops the device from contacting certain domains known to host malware." +msgstr "" + +msgctxt "preferences-view" +msgid "When enabled, this feature stops the device from contacting certain domains known to track users." +msgstr "" + +msgctxt "preferences-view" +msgid "When enabled, this feature stops the device from contacting certain known ad domains." +msgstr "" + +msgctxt "preferences-view" +msgid "When enabled, this feature stops the device from contacting certain websites and services known to host adult content." +msgstr "" + +msgctxt "preferences-view" +msgid "When enabled, this feature stops the device from contacting certain websites and services known to host gambling content." +msgstr "" + msgctxt "redeem-voucher-alert" msgid "Cancel" msgstr "" diff --git a/gui/src/renderer/components/AriaGroup.tsx b/gui/src/renderer/components/AriaGroup.tsx index bf5b2d7439..9f7755cb6a 100644 --- a/gui/src/renderer/components/AriaGroup.tsx +++ b/gui/src/renderer/components/AriaGroup.tsx @@ -29,11 +29,15 @@ export function AriaControlGroup(props: IAriaGroupProps) { } interface IAriaDescriptionContext { + describedId: string; descriptionId?: string; setHasDescription: (value: boolean) => void; } const AriaDescriptionContext = React.createContext<IAriaDescriptionContext>({ + get describedId(): string { + throw new Error('Missing AriaDescriptionContext.Provider'); + }, setHasDescription(_value) { throw new Error('Missing AriaDescriptionContext.Provider'); }, @@ -45,6 +49,7 @@ export function AriaDescriptionGroup(props: IAriaGroupProps) { const contextValue = useMemo( () => ({ + describedId: `${id}-described`, descriptionId: hasDescription ? `${id}-description` : undefined, setHasDescription, }), @@ -137,9 +142,10 @@ export function AriaLabel(props: IAriaElementProps) { } export function AriaDescribed(props: IAriaElementProps) { - const { descriptionId } = useContext(AriaDescriptionContext); + const { describedId, descriptionId } = useContext(AriaDescriptionContext); return React.cloneElement(props.children, { + id: describedId, 'aria-describedby': descriptionId, }); } @@ -156,3 +162,8 @@ export function AriaDescription(props: IAriaElementProps) { id: descriptionId, }); } + +export function AriaDetails(props: IAriaElementProps) { + const { describedId } = useContext(AriaDescriptionContext); + return React.cloneElement(props.children, { 'aria-details': describedId }); +} diff --git a/gui/src/renderer/components/InfoButton.tsx b/gui/src/renderer/components/InfoButton.tsx new file mode 100644 index 0000000000..52d92e18d6 --- /dev/null +++ b/gui/src/renderer/components/InfoButton.tsx @@ -0,0 +1,65 @@ +import styled from 'styled-components'; + +import { colors } from '../../config.json'; +import { messages } from '../../shared/gettext'; +import { useBoolean } from '../lib/utilityHooks'; +import * as AppButton from './AppButton'; +import ImageView from './ImageView'; +import { ModalAlert, ModalAlertType } from './Modal'; + +const StyledInfoButton = styled.button({ + margin: '0 16px 0 0', + borderWidth: 0, + padding: 0, + cursor: 'default', + backgroundColor: 'transparent', +}); + +interface IInfoIconProps { + className?: string; +} + +export function InfoIcon(props: IInfoIconProps) { + return ( + <ImageView + source="icon-info" + width={18} + tintColor={colors.white} + tintHoverColor={colors.white80} + className={props.className} + /> + ); +} + +interface IInfoButtonProps extends React.HTMLAttributes<HTMLButtonElement> { + message?: string; + children?: React.ReactNode; +} + +export default function InfoButton(props: IInfoButtonProps) { + const { message, children, ...otherProps } = props; + const [isOpen, show, hide] = useBoolean(false); + + return ( + <> + <StyledInfoButton + onClick={show} + aria-label={messages.pgettext('accessibility', 'More information')} + {...otherProps}> + <InfoIcon /> + </StyledInfoButton> + <ModalAlert + isOpen={isOpen} + message={props.message} + type={ModalAlertType.info} + buttons={[ + <AppButton.BlueButton key="back" onClick={hide}> + {messages.gettext('Got it!')} + </AppButton.BlueButton>, + ]} + close={hide}> + {props.children} + </ModalAlert> + </> + ); +} diff --git a/gui/src/renderer/components/Preferences.tsx b/gui/src/renderer/components/Preferences.tsx index 0d6fea3809..001f367f87 100644 --- a/gui/src/renderer/components/Preferences.tsx +++ b/gui/src/renderer/components/Preferences.tsx @@ -1,17 +1,16 @@ 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 { AriaDescription, AriaDetails, AriaInput, AriaInputGroup, AriaLabel } from './AriaGroup'; import * as Cell from './cell'; -import ImageView from './ImageView'; +import InfoButton from './InfoButton'; import { BackAction } from './KeyboardNavigation'; import { Layout } from './Layout'; -import { ModalAlert, ModalAlertType } from './Modal'; +import { ModalAlert, ModalAlertType, ModalMessage } from './Modal'; import { NavigationBar, NavigationContainer, @@ -19,7 +18,12 @@ import { NavigationScrollbars, TitleBarItem, } from './NavigationBar'; -import { StyledContainer, StyledContent, StyledSeparator } from './PreferencesStyles'; +import { + StyledContainer, + StyledContent, + StyledInfoIcon, + StyledSeparator, +} from './PreferencesStyles'; import SettingsHeader, { HeaderTitle } from './SettingsHeader'; export interface IProps { @@ -76,10 +80,17 @@ export default class Preferences extends React.Component<IProps, IState> { <StyledContent> <Cell.CellButton onClick={this.showKillSwitchInfo}> - <Cell.InputLabel> - {messages.pgettext('preferences-view', 'Kill switch')} - </Cell.InputLabel> - <ImageView source="icon-info" width={18} tintColor={colors.white} /> + <AriaInputGroup> + <AriaLabel> + <Cell.InputLabel> + {messages.pgettext('preferences-view', 'Kill switch')} + </Cell.InputLabel> + </AriaLabel> + <StyledInfoIcon /> + <AriaInput> + <Cell.Switch isOn disabled /> + </AriaInput> + </AriaInputGroup> </Cell.CellButton> <StyledSeparator height={20} /> @@ -133,6 +144,22 @@ export default class Preferences extends React.Component<IProps, IState> { {messages.pgettext('preferences-view', 'Block ads')} </Cell.InputLabel> </AriaLabel> + <AriaDetails> + <InfoButton> + <ModalMessage> + {messages.pgettext( + 'preferences-view', + 'When enabled, this feature stops the device from contacting certain known ad domains.', + )} + </ModalMessage> + <ModalMessage> + {messages.pgettext( + 'preferences-view', + 'Warning: This might cause issues on certain websites, services, and programs.', + )} + </ModalMessage> + </InfoButton> + </AriaDetails> <AriaInput> <Cell.Switch isOn={ @@ -152,6 +179,22 @@ export default class Preferences extends React.Component<IProps, IState> { {messages.pgettext('preferences-view', 'Block trackers')} </Cell.InputLabel> </AriaLabel> + <AriaDetails> + <InfoButton> + <ModalMessage> + {messages.pgettext( + 'preferences-view', + 'When enabled, this feature stops the device from contacting certain domains known to track users.', + )} + </ModalMessage> + <ModalMessage> + {messages.pgettext( + 'preferences-view', + 'Warning: This might cause issues on certain websites, services, and programs.', + )} + </ModalMessage> + </InfoButton> + </AriaDetails> <AriaInput> <Cell.Switch isOn={ @@ -171,6 +214,22 @@ export default class Preferences extends React.Component<IProps, IState> { {messages.pgettext('preferences-view', 'Block malware')} </Cell.InputLabel> </AriaLabel> + <AriaDetails> + <InfoButton> + <ModalMessage> + {messages.pgettext( + 'preferences-view', + 'When enabled, this feature stops the device from contacting certain domains known to host malware.', + )} + </ModalMessage> + <ModalMessage> + {messages.pgettext( + 'preferences-view', + 'Warning: This is not an anti-virus and should not be treated as such, this is just an extra layer of protection.', + )} + </ModalMessage> + </InfoButton> + </AriaDetails> <AriaInput> <Cell.Switch isOn={ @@ -190,6 +249,14 @@ export default class Preferences extends React.Component<IProps, IState> { {messages.pgettext('preferences-view', 'Block adult content')} </Cell.InputLabel> </AriaLabel> + <AriaDetails> + <InfoButton + message={messages.pgettext( + 'preferences-view', + 'When enabled, this feature stops the device from contacting certain websites and services known to host adult content.', + )} + /> + </AriaDetails> <AriaInput> <Cell.Switch isOn={ @@ -209,6 +276,14 @@ export default class Preferences extends React.Component<IProps, IState> { {messages.pgettext('preferences-view', 'Block gambling')} </Cell.InputLabel> </AriaLabel> + <AriaDetails> + <InfoButton + message={messages.pgettext( + 'preferences-view', + 'When enabled, this feature stops the device from contacting certain websites and services known to host gambling content.', + )} + /> + </AriaDetails> <AriaInput> <Cell.Switch isOn={ diff --git a/gui/src/renderer/components/PreferencesStyles.tsx b/gui/src/renderer/components/PreferencesStyles.tsx index 704934769a..81ee5c1928 100644 --- a/gui/src/renderer/components/PreferencesStyles.tsx +++ b/gui/src/renderer/components/PreferencesStyles.tsx @@ -1,6 +1,7 @@ import styled from 'styled-components'; import { colors } from '../../config.json'; +import { InfoIcon } from './InfoButton'; import { Container } from './Layout'; export const StyledContainer = styled(Container)({ @@ -17,3 +18,7 @@ export const StyledContent = styled.div({ export const StyledSeparator = styled.div((props: { height?: number }) => ({ height: `${props.height ?? 1}px`, })); + +export const StyledInfoIcon = styled(InfoIcon)({ + marginRight: '16px', +}); |
