diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-02-21 10:42:54 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-02-22 11:29:25 +0100 |
| commit | 2f009ab1b2136143ebbf106661b5390b33d7c1a3 (patch) | |
| tree | 6883c3feb9206045871857c6d79e00722952de76 /gui/src | |
| parent | 7aea025585bf95654bdd216c48edd3769057aba0 (diff) | |
| download | mullvadvpn-2f009ab1b2136143ebbf106661b5390b33d7c1a3.tar.xz mullvadvpn-2f009ab1b2136143ebbf106661b5390b33d7c1a3.zip | |
Show warning about blocking connection on login view
Diffstat (limited to 'gui/src')
| -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 |
4 files changed, 103 insertions, 7 deletions
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) => { |
