summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2020-10-13 14:16:32 +0200
committerOskar Nyberg <oskar@mullvad.net>2020-10-13 14:16:32 +0200
commit8ed83fceec60a0b55011c35db6bdcec31d7e3971 (patch)
tree915094f094fb05db45f48bb4530d9cde08d7b195
parentb1e1fd6d444bba2192c372f7a23242fe2daebfdc (diff)
parent4d11817ef253b60ebec3107130d449fcc4f4d038 (diff)
downloadmullvadvpn-8ed83fceec60a0b55011c35db6bdcec31d7e3971.tar.xz
mullvadvpn-8ed83fceec60a0b55011c35db6bdcec31d7e3971.zip
Merge branch 'fix-icon-flickering' into master
-rw-r--r--gui/src/renderer/components/ImageView.tsx9
-rw-r--r--gui/src/renderer/components/TunnelControl.tsx142
2 files changed, 82 insertions, 69 deletions
diff --git a/gui/src/renderer/components/ImageView.tsx b/gui/src/renderer/components/ImageView.tsx
index fa57985363..368b72cd9e 100644
--- a/gui/src/renderer/components/ImageView.tsx
+++ b/gui/src/renderer/components/ImageView.tsx
@@ -1,14 +1,14 @@
import path from 'path';
-import * as React from 'react';
+import React, { useMemo } from 'react';
import styled from 'styled-components';
export interface IImageViewProps extends IImageMaskProps {
+ source: string;
onClick?: (event: React.MouseEvent) => void;
className?: string;
}
interface IImageMaskProps extends React.HTMLAttributes<HTMLElement> {
- source: string;
width?: number;
height?: number;
disabled?: boolean;
@@ -26,7 +26,6 @@ const ImageMask = styled.div((props: IImageMaskProps) => {
const maskWidth = props.width ? `${props.width}px` : 'auto';
const maskHeight = props.height ? `${props.height}px` : 'auto';
return {
- maskImage: `url('${props.source}')`,
maskRepeat: 'no-repeat',
maskSize: `${maskWidth} ${maskHeight}`,
maskPosition: 'center',
@@ -45,10 +44,12 @@ export default function ImageView(props: IImageViewProps) {
? props.source
: `../../assets/images/${props.source}.svg`;
+ const style = useMemo(() => ({ WebkitMaskImage: `url('${url}')` }), [url]);
+
if (props.tintColor) {
const { source: _source, ...otherProps } = props;
return (
- <ImageMask source={url} {...otherProps}>
+ <ImageMask style={style} {...otherProps}>
<HiddenImage src={url} width={props.width} height={props.height} />
</ImageMask>
);
diff --git a/gui/src/renderer/components/TunnelControl.tsx b/gui/src/renderer/components/TunnelControl.tsx
index e0345c0fbb..016c360e4a 100644
--- a/gui/src/renderer/components/TunnelControl.tsx
+++ b/gui/src/renderer/components/TunnelControl.tsx
@@ -75,59 +75,6 @@ const SelectedLocationChevron = styled(AppButton.Icon)({
export default class TunnelControl extends React.Component<ITunnelControlProps> {
public render() {
- const SwitchLocation = () => {
- return (
- <SwitchLocationButton onClick={this.props.onSelectLocation}>
- {messages.pgettext('tunnel-control', 'Switch location')}
- </SwitchLocationButton>
- );
- };
-
- const SelectedLocation = () => (
- <SwitchLocationButton
- onClick={this.props.onSelectLocation}
- aria-label={sprintf(
- messages.pgettext('accessibility', 'Select location. Current location is %(location)s'),
- { location: this.props.selectedRelayName },
- )}>
- <AppButton.Label>{this.props.selectedRelayName}</AppButton.Label>
- <SelectedLocationChevron height={12} width={7} source="icon-chevron" />
- </SwitchLocationButton>
- );
-
- const Connect = () => (
- <AppButton.GreenButton onClick={this.props.onConnect}>
- {messages.pgettext('tunnel-control', 'Secure my connection')}
- </AppButton.GreenButton>
- );
-
- const Disconnect = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => (
- <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
- {messages.gettext('Disconnect')}
- </AppButton.RedTransparentButton>
- );
-
- const Cancel = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => (
- <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
- {messages.gettext('Cancel')}
- </AppButton.RedTransparentButton>
- );
-
- const Dismiss = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => (
- <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
- {messages.gettext('Dismiss')}
- </AppButton.RedTransparentButton>
- );
-
- const Reconnect = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => (
- <AppButton.RedTransparentButton
- onClick={this.props.onReconnect}
- aria-label={messages.gettext('Reconnect')}
- {...props}>
- <ImageView height={22} width={22} source="icon-reload" tintColor="white" />
- </AppButton.RedTransparentButton>
- );
-
let state = this.props.tunnelState.state;
switch (this.props.tunnelState.state) {
@@ -159,8 +106,8 @@ export default class TunnelControl extends React.Component<ITunnelControlProps>
<ConnectionPanelContainer />
</Body>
<Footer>
- <SwitchLocation />
- <MultiButton mainButton={Cancel} sideButton={Reconnect} />
+ {this.switchLocationButton()}
+ <MultiButton mainButton={this.cancelButton} sideButton={this.reconnectButton} />
</Footer>
</Wrapper>
);
@@ -176,8 +123,8 @@ export default class TunnelControl extends React.Component<ITunnelControlProps>
<ConnectionPanelContainer />
</Body>
<Footer>
- <SwitchLocation />
- <MultiButton mainButton={Disconnect} sideButton={Reconnect} />
+ {this.switchLocationButton()}
+ <MultiButton mainButton={this.disconnectButton} sideButton={this.reconnectButton} />
</Footer>
</Wrapper>
);
@@ -193,8 +140,8 @@ export default class TunnelControl extends React.Component<ITunnelControlProps>
<Secured displayStyle={SecuredDisplayStyle.failedToSecure} />
</Body>
<Footer>
- <SwitchLocation />
- <MultiButton mainButton={Dismiss} sideButton={Reconnect} />
+ {this.switchLocationButton()}
+ <MultiButton mainButton={this.dismissButton} sideButton={this.reconnectButton} />
</Footer>
</Wrapper>
);
@@ -205,8 +152,8 @@ export default class TunnelControl extends React.Component<ITunnelControlProps>
<Secured displayStyle={SecuredDisplayStyle.blocked} />
</Body>
<Footer>
- <SwitchLocation />
- <MultiButton mainButton={Cancel} sideButton={Reconnect} />
+ {this.switchLocationButton()}
+ <MultiButton mainButton={this.cancelButton} sideButton={this.reconnectButton} />
</Footer>
</Wrapper>
);
@@ -220,8 +167,8 @@ export default class TunnelControl extends React.Component<ITunnelControlProps>
<Location>{this.renderCountry()}</Location>
</Body>
<Footer>
- <SelectedLocation />
- <Connect />
+ {this.selectLocationButton()}
+ {this.connectButton()}
</Footer>
</Wrapper>
);
@@ -237,8 +184,8 @@ export default class TunnelControl extends React.Component<ITunnelControlProps>
<Location>{this.renderCountry()}</Location>
</Body>
<Footer>
- <SelectedLocation />
- <Connect />
+ {this.selectLocationButton()}
+ {this.connectButton()}
</Footer>
</Wrapper>
);
@@ -256,4 +203,69 @@ export default class TunnelControl extends React.Component<ITunnelControlProps>
private renderCountry() {
return <StyledMarquee>{this.props.country}</StyledMarquee>;
}
+
+ private switchLocationButton() {
+ return (
+ <SwitchLocationButton onClick={this.props.onSelectLocation}>
+ {messages.pgettext('tunnel-control', 'Switch location')}
+ </SwitchLocationButton>
+ );
+ }
+
+ private selectLocationButton() {
+ return (
+ <SwitchLocationButton
+ onClick={this.props.onSelectLocation}
+ aria-label={sprintf(
+ messages.pgettext('accessibility', 'Select location. Current location is %(location)s'),
+ { location: this.props.selectedRelayName },
+ )}>
+ <AppButton.Label>{this.props.selectedRelayName}</AppButton.Label>
+ <SelectedLocationChevron height={12} width={7} source="icon-chevron" />
+ </SwitchLocationButton>
+ );
+ }
+
+ private connectButton() {
+ return (
+ <AppButton.GreenButton onClick={this.props.onConnect}>
+ {messages.pgettext('tunnel-control', 'Secure my connection')}
+ </AppButton.GreenButton>
+ );
+ }
+
+ private disconnectButton = (props: AppButton.IProps) => {
+ return (
+ <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
+ {messages.gettext('Disconnect')}
+ </AppButton.RedTransparentButton>
+ );
+ };
+
+ private cancelButton = (props: AppButton.IProps) => {
+ return (
+ <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
+ {messages.gettext('Cancel')}
+ </AppButton.RedTransparentButton>
+ );
+ };
+
+ private dismissButton = (props: AppButton.IProps) => {
+ return (
+ <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
+ {messages.gettext('Dismiss')}
+ </AppButton.RedTransparentButton>
+ );
+ };
+
+ private reconnectButton = (props: AppButton.IProps) => {
+ return (
+ <AppButton.RedTransparentButton
+ onClick={this.props.onReconnect}
+ aria-label={messages.gettext('Reconnect')}
+ {...props}>
+ <ImageView height={22} width={22} source="icon-reload" tintColor="white" />
+ </AppButton.RedTransparentButton>
+ );
+ };
}