diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-02-22 11:29:46 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-02-22 11:29:46 +0100 |
| commit | 79702044ae55a4af48cfbdd4bc3f13d26b3e1672 (patch) | |
| tree | 0ebb1377449f1889afd3babea66407a57f9a8204 | |
| parent | 7aea025585bf95654bdd216c48edd3769057aba0 (diff) | |
| parent | ffc9971f8a5ab51b5b05b09f282fcae4b916b41b (diff) | |
| download | mullvadvpn-79702044ae55a4af48cfbdd4bc3f13d26b3e1672.tar.xz mullvadvpn-79702044ae55a4af48cfbdd4bc3f13d26b3e1672.zip | |
Merge branch 'add-blocking-message-on-login-page'
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rw-r--r-- | gui/locales/messages.pot | 26 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 4 | ||||
| -rw-r--r-- | gui/src/renderer/components/Login.tsx | 63 | ||||
| -rw-r--r-- | gui/src/renderer/components/LoginStyles.tsx | 37 | ||||
| -rw-r--r-- | gui/src/renderer/containers/LoginPage.tsx | 6 |
6 files changed, 129 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index c4a31afc81..77852038c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,9 @@ Line wrap the file at 100 chars. Th ## [Unreleased] ### Added +- Show warning message when blocking internet while logged out, and make it possible to unblock the + connection from the login view. + #### Windows - Detect mounting and dismounting of volumes, such as VeraCrypt volumes or USB drives, and exclude paths from the tunnel correctly when these occur. This sometimes only works diff --git a/gui/locales/messages.pot b/gui/locales/messages.pot index 760070ae6c..6effa79b61 100644 --- a/gui/locales/messages.pot +++ b/gui/locales/messages.pot @@ -78,6 +78,9 @@ msgstr "" msgid "BLOCKED CONNECTION" msgstr "" +msgid "Blocking internet" +msgstr "" + msgid "Buy credit" msgstr "" @@ -102,6 +105,9 @@ msgstr "" msgid "Default" msgstr "" +msgid "Disable" +msgstr "" + msgid "Disconnect" msgstr "" @@ -173,6 +179,9 @@ msgstr "" msgid "UDP" msgstr "" +msgid "Unblock" +msgstr "" + msgid "UNSECURED CONNECTION" msgstr "" @@ -565,6 +574,14 @@ msgctxt "launch-view" msgid "Connecting to Mullvad system service..." msgstr "" +#. This is a warning message shown when the app is blocking the users +#. internet connection while logged out. +#. Available placeholder: +#. %(alwaysRequireVpnSettingsName)s - The translation of "Always require VPN" +msgctxt "login-view" +msgid "**%(alwaysRequireVpnSettingsName)s** is enabled. Disable it to unblock your connection." +msgstr "" + msgctxt "login-view" msgid "Account created" msgstr "" @@ -613,6 +630,12 @@ msgctxt "login-view" msgid "Login failed" msgstr "" +#. This is a warning message shown when the app is blocking the users +#. internet connection while logged out. +msgctxt "login-view" +msgid "Our kill switch is currently blocking your connection." +msgstr "" + msgctxt "login-view" msgid "Please wait" msgstr "" @@ -1374,9 +1397,6 @@ msgstr "" msgid "Blocking all connections" msgstr "" -msgid "Blocking internet" -msgstr "" - msgid "Copied Mullvad account number to clipboard" msgstr "" diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index e9aadedcc4..bd7b2865e6 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -381,11 +381,11 @@ export default class AppRenderer { actions.settings.updateBridgeState(bridgeState); } - public async setBlockWhenDisconnected(blockWhenDisconnected: boolean) { + public setBlockWhenDisconnected = async (blockWhenDisconnected: boolean) => { const actions = this.reduxActions; await IpcRendererEventChannel.settings.setBlockWhenDisconnected(blockWhenDisconnected); actions.settings.updateBlockWhenDisconnected(blockWhenDisconnected); - } + }; public async setOpenVpnMssfix(mssfix?: number) { const actions = this.reduxActions; diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx index c7fd1f45cd..bdeb6bdb4b 100644 --- a/gui/src/renderer/components/Login.tsx +++ b/gui/src/renderer/components/Login.tsx @@ -17,6 +17,9 @@ import { StyledAccountDropdownRemoveIcon, StyledAccountInputBackdrop, StyledAccountInputGroup, + StyledBlockMessage, + StyledBlockMessageContainer, + StyledBlockTitle, StyledDropdownSpacer, StyledFooter, StyledInput, @@ -27,16 +30,21 @@ import { StyledStatusIcon, StyledSubtitle, StyledTitle, + StyledTopInfo, } from './LoginStyles'; import { AccountToken } from '../../shared/daemon-rpc-types'; import { LoginState } from '../redux/account/reducers'; import { AriaControlGroup, AriaControlled, AriaControls } from './AriaGroup'; +import { useSelector } from '../redux/store'; +import { useAppContext } from '../context'; +import { formatMarkdown } from '../markdown-formatter'; interface IProps { accountToken?: AccountToken; accountHistory?: AccountToken; loginState: LoginState; + showBlockMessage: boolean; openExternalLink: (type: string) => void; login: (accountToken: AccountToken) => void; resetLoginError: () => void; @@ -90,8 +98,11 @@ export default class Login extends React.Component<IProps, IState> { <HeaderBarSettingsButton /> </Header> <Container> + <StyledTopInfo> + {this.props.showBlockMessage ? <BlockMessage /> : this.getStatusIcon()} + </StyledTopInfo> + <StyledLoginForm> - {this.getStatusIcon()} <StyledTitle aria-live="polite">{this.formTitle()}</StyledTitle> {this.createLoginForm()} @@ -392,3 +403,53 @@ function AccountDropdownItem(props: IAccountDropdownItemProps) { </> ); } + +function BlockMessage() { + const { setBlockWhenDisconnected, disconnectTunnel } = useAppContext(); + const tunnelState = useSelector((state) => state.connection.status); + const blockWhenDisconnected = useSelector((state) => state.settings.blockWhenDisconnected); + + const unlock = useCallback(() => { + if (blockWhenDisconnected) { + void setBlockWhenDisconnected(false); + } + + if (tunnelState.state === 'error') { + void disconnectTunnel(); + } + }, [blockWhenDisconnected, tunnelState, setBlockWhenDisconnected, disconnectTunnel]); + + const alwaysRequireVpnSettingsName = messages.pgettext( + 'advanced-settings-view', + 'Always require VPN', + ); + const message = formatMarkdown( + blockWhenDisconnected + ? sprintf( + // TRANSLATORS: This is a warning message shown when the app is blocking the users + // TRANSLATORS: internet connection while logged out. + // TRANSLATORS: Available placeholder: + // TRANSLATORS: %(alwaysRequireVpnSettingsName)s - The translation of "Always require VPN" + messages.pgettext( + 'login-view', + '**%(alwaysRequireVpnSettingsName)s** is enabled. Disable it to unblock your connection.', + ), + { alwaysRequireVpnSettingsName }, + ) + : // This makes the translator comment appear on it's own line. + // TRANSLATORS: This is a warning message shown when the app is blocking the users + // TRANSLATORS: internet connection while logged out. + messages.pgettext('login-view', 'Our kill switch is currently blocking your connection.'), + ); + const buttonText = blockWhenDisconnected + ? messages.gettext('Disable') + : messages.gettext('Unblock'); + + return ( + <StyledBlockMessageContainer> + <StyledBlockTitle>{messages.gettext('Blocking internet')}</StyledBlockTitle> + <StyledBlockMessage>{message}</StyledBlockMessage> + <AppButton.RedButton onClick={unlock}>{buttonText}</AppButton.RedButton> + </StyledBlockMessageContainer> + ); +} diff --git a/gui/src/renderer/components/LoginStyles.tsx b/gui/src/renderer/components/LoginStyles.tsx index 6d2a6328f4..f3302a397b 100644 --- a/gui/src/renderer/components/LoginStyles.tsx +++ b/gui/src/renderer/components/LoginStyles.tsx @@ -2,7 +2,7 @@ import styled from 'styled-components'; import { colors } from '../../config.json'; import ImageView from './ImageView'; import * as Cell from './cell'; -import { hugeText, largeText, tinyText } from './common-styles'; +import { hugeText, largeText, smallText, tinyText } from './common-styles'; import FormattableTextInput from './FormattableTextInput'; export const StyledAccountDropdownContainer = styled.ul({ @@ -67,12 +67,19 @@ export const StyledAccountDropdownItemButtonLabel = styled(Cell.Label)(largeText }, }); +export const StyledTopInfo = styled.div({ + display: 'flex', + justifyContent: 'center', + flex: 1, +}); + export const StyledFooter = styled.div({}, (props: { show: boolean }) => ({ - position: 'absolute', + position: 'relative', width: '100%', bottom: 0, transform: `translateY(${props.show ? 0 : 100}%)`, display: 'flex', + flex: '0', flexDirection: 'column', padding: '18px 22px 22px', backgroundColor: colors.darkBlue, @@ -81,6 +88,7 @@ export const StyledFooter = styled.div({}, (props: { show: boolean }) => ({ export const StyledStatusIcon = styled.div({ display: 'flex', + alignSelf: 'end', flex: 0, marginBottom: '30px', justifyContent: 'center', @@ -90,11 +98,10 @@ export const StyledStatusIcon = styled.div({ export const StyledLoginForm = styled.div({ display: 'flex', - flex: 1, + flex: '0 1 225px', flexDirection: 'column', overflow: 'visible', padding: '0 22px', - margin: '83px 0 0', }); interface IStyledAccountInputGroupProps { @@ -164,3 +171,25 @@ export const StyledInput = styled(FormattableTextInput)(largeText, { color: colors.blue40, }, }); + +export const StyledBlockMessageContainer = styled.div({ + display: 'flex', + flexDirection: 'column', + flex: 1, + alignSelf: 'start', + backgroundColor: colors.darkBlue, + borderRadius: '8px', + margin: '5px 16px 10px', + padding: '16px', +}); + +export const StyledBlockTitle = styled.div(smallText, { + color: colors.white, + marginBottom: '5px', + fontWeight: 700, +}); + +export const StyledBlockMessage = styled.div(tinyText, { + color: colors.white, + marginBottom: '10px', +}); diff --git a/gui/src/renderer/containers/LoginPage.tsx b/gui/src/renderer/containers/LoginPage.tsx index 6797f40d3e..a6c494c601 100644 --- a/gui/src/renderer/containers/LoginPage.tsx +++ b/gui/src/renderer/containers/LoginPage.tsx @@ -6,11 +6,17 @@ import accountActions from '../redux/account/actions'; import { IReduxState, ReduxDispatch } from '../redux/store'; const mapStateToProps = (state: IReduxState) => { + const tunnelState = state.connection.status; + const blockWhenDisconnected = state.settings.blockWhenDisconnected; const { accountToken, accountHistory, status } = state.account; + + const showBlockMessage = tunnelState.state === 'error' || blockWhenDisconnected; + return { accountToken, accountHistory, loginState: status, + showBlockMessage, }; }; const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => { |
