summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-05-05 11:14:37 +0200
committerOskar Nyberg <oskar@mullvad.net>2022-05-05 11:14:37 +0200
commit3a19900e51ca874e8202bfbd2853662a0652863e (patch)
treec938ddc4471c35a1067212ec83f2a66c42cacebc
parent7325107e01d8ff4c9cd405de36ccaa254d4e40c8 (diff)
parente6fd227d8e788e5d89c3fae10791626c706daf4b (diff)
downloadmullvadvpn-3a19900e51ca874e8202bfbd2853662a0652863e.tar.xz
mullvadvpn-3a19900e51ca874e8202bfbd2853662a0652863e.zip
Merge branch 'add-block-setting-info'
-rw-r--r--gui/locales/messages.pot32
-rw-r--r--gui/src/renderer/components/AriaGroup.tsx13
-rw-r--r--gui/src/renderer/components/InfoButton.tsx65
-rw-r--r--gui/src/renderer/components/Preferences.tsx93
-rw-r--r--gui/src/renderer/components/PreferencesStyles.tsx5
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',
+});