summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2020-05-27 17:47:08 +0200
committerOskar Nyberg <oskar@mullvad.net>2020-05-27 17:47:08 +0200
commit3a801671a2dab9a6359ca0cc0b581193fb3649b7 (patch)
treeef576608e6a643630aa3bc3762523e84c36452f6 /gui/src
parente7824eb7d2c8368f6aefa157155e9e5a3beb7a76 (diff)
parenta03dc3d0a0dc22b234c49a61590173aa8a401c9d (diff)
downloadmullvadvpn-3a801671a2dab9a6359ca0cc0b581193fb3649b7.tar.xz
mullvadvpn-3a801671a2dab9a6359ca0cc0b581193fb3649b7.zip
Merge branch 'convert-app-button-to-styled-components'
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/components/Account.tsx15
-rw-r--r--gui/src/renderer/components/AccountStyles.tsx12
-rw-r--r--gui/src/renderer/components/AdvancedSettings.tsx4
-rw-r--r--gui/src/renderer/components/AppButton.tsx208
-rw-r--r--gui/src/renderer/components/AppButtonStyles.tsx92
-rw-r--r--gui/src/renderer/components/ExpiredAccountErrorView.tsx18
-rw-r--r--gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx11
-rw-r--r--gui/src/renderer/components/Login.tsx2
-rw-r--r--gui/src/renderer/components/MultiButton.tsx71
-rw-r--r--gui/src/renderer/components/NotificationBanner.tsx2
-rw-r--r--gui/src/renderer/components/RedeemVoucher.tsx11
-rw-r--r--gui/src/renderer/components/Settings.tsx2
-rw-r--r--gui/src/renderer/components/Support.tsx27
-rw-r--r--gui/src/renderer/components/SupportStyles.tsx12
-rw-r--r--gui/src/renderer/components/TunnelControl.tsx40
-rw-r--r--gui/src/renderer/components/WireguardKeys.tsx6
16 files changed, 234 insertions, 299 deletions
diff --git a/gui/src/renderer/components/Account.tsx b/gui/src/renderer/components/Account.tsx
index 7863040f83..352ed1dad3 100644
--- a/gui/src/renderer/components/Account.tsx
+++ b/gui/src/renderer/components/Account.tsx
@@ -1,21 +1,22 @@
import * as React from 'react';
import AccountExpiry from '../../shared/account-expiry';
import { messages } from '../../shared/gettext';
-import styles, {
+import {
AccountContainer,
AccountFooter,
AccountOutOfTime,
AccountRow,
AccountRowLabel,
AccountRowValue,
+ StyledBuyCreditButton,
StyledContainer,
+ StyledRedeemVoucherButton,
} from './AccountStyles';
import AccountTokenLabel from './AccountTokenLabel';
import * as AppButton from './AppButton';
import { Layout } from './Layout';
import { ModalContainer } from './Modal';
import { BackBarItem, NavigationBar, NavigationItems } from './NavigationBar';
-import { RedeemVoucherButton } from './RedeemVoucher';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
import { AccountToken } from '../../shared/daemon-rpc-types';
@@ -73,16 +74,16 @@ export default class Account extends React.Component<IProps> {
<AccountFooter>
<AppButton.BlockingButton
disabled={this.props.isOffline}
- onPress={this.props.onBuyMore}>
- <AppButton.GreenButton style={styles.button}>
+ onClick={this.props.onBuyMore}>
+ <StyledBuyCreditButton>
<AppButton.Label>{messages.gettext('Buy more credit')}</AppButton.Label>
<AppButton.Icon source="icon-extLink" height={16} width={16} />
- </AppButton.GreenButton>
+ </StyledBuyCreditButton>
</AppButton.BlockingButton>
- <RedeemVoucherButton style={styles.button} />
+ <StyledRedeemVoucherButton />
- <AppButton.RedButton onPress={this.props.onLogout}>
+ <AppButton.RedButton onClick={this.props.onLogout}>
{messages.pgettext('account-view', 'Log out')}
</AppButton.RedButton>
</AccountFooter>
diff --git a/gui/src/renderer/components/AccountStyles.tsx b/gui/src/renderer/components/AccountStyles.tsx
index 970309e4f8..f66485e3d6 100644
--- a/gui/src/renderer/components/AccountStyles.tsx
+++ b/gui/src/renderer/components/AccountStyles.tsx
@@ -1,7 +1,8 @@
-import { Styles } from 'reactxp';
import styled from 'styled-components';
import { colors } from '../../config.json';
+import * as AppButton from './AppButton';
import { Container } from './Layout';
+import { RedeemVoucherButton } from './RedeemVoucher';
export const StyledContainer = styled(Container)({
backgroundColor: colors.darkBlue,
@@ -51,8 +52,9 @@ export const AccountFooter = styled.div({
padding: '0 24px',
});
-export default {
- button: Styles.createViewStyle({
- marginBottom: 24,
- }),
+const buttonStyle = {
+ marginBottom: 24,
};
+
+export const StyledRedeemVoucherButton = styled(RedeemVoucherButton)(buttonStyle);
+export const StyledBuyCreditButton = styled(AppButton.GreenButton)(buttonStyle);
diff --git a/gui/src/renderer/components/AdvancedSettings.tsx b/gui/src/renderer/components/AdvancedSettings.tsx
index 4fa10adde9..0645f03ff7 100644
--- a/gui/src/renderer/components/AdvancedSettings.tsx
+++ b/gui/src/renderer/components/AdvancedSettings.tsx
@@ -402,10 +402,10 @@ export default class AdvancedSettings extends Component<IProps, IState> {
<ModalAlert
type={ModalAlertType.Info}
buttons={[
- <AppButton.RedButton key="confirm" onPress={this.confirmEnableBlockWhenDisconnected}>
+ <AppButton.RedButton key="confirm" onClick={this.confirmEnableBlockWhenDisconnected}>
{messages.pgettext('advanced-settings-view', 'Enable anyway')}
</AppButton.RedButton>,
- <AppButton.BlueButton key="back" onPress={this.hideConfirmBlockWhenDisconnectedAlert}>
+ <AppButton.BlueButton key="back" onClick={this.hideConfirmBlockWhenDisconnectedAlert}>
{messages.gettext('Back')}
</AppButton.BlueButton>,
]}>
diff --git a/gui/src/renderer/components/AppButton.tsx b/gui/src/renderer/components/AppButton.tsx
index e1c37c014b..c0731917d0 100644
--- a/gui/src/renderer/components/AppButton.tsx
+++ b/gui/src/renderer/components/AppButton.tsx
@@ -1,56 +1,31 @@
import log from 'electron-log';
-import * as React from 'react';
-import { Button, Component, Styles, Text, Types, UserInterface, View } from 'reactxp';
+import React, { useContext } from 'react';
+import styled from 'styled-components';
import { colors } from '../../config.json';
-import consumePromise from '../../shared/promise';
-import styles from './AppButtonStyles';
+import {
+ StyledButton,
+ StyledButtonContent,
+ StyledLabel,
+ StyledLabelContainer,
+} from './AppButtonStyles';
import ImageView from './ImageView';
const ButtonContext = React.createContext({
textAdjustment: 0,
- textRef: React.createRef<PrivateLabel>(),
+ textRef: React.createRef<HTMLDivElement>(),
});
interface ILabelProps {
children?: React.ReactText;
}
-interface IPrivateLabelProps {
- textAdjustment: number;
- children?: React.ReactText;
-}
-
-class PrivateLabel extends Component<IPrivateLabelProps> {
- public render() {
- const { textAdjustment, children } = this.props;
- const textAdjustmentStyle = Styles.createViewStyle(
- {
- paddingRight: textAdjustment > 0 ? textAdjustment : 0,
- paddingLeft: textAdjustment < 0 ? Math.abs(textAdjustment) : 0,
- },
- false,
- );
-
- return (
- <View style={[styles.labelContainer, textAdjustmentStyle]}>
- <Text style={styles.label}>{children}</Text>
- </View>
- );
- }
-}
-
-export class Label extends Component<ILabelProps> {
- public render() {
- return (
- <ButtonContext.Consumer>
- {(context) => (
- <PrivateLabel ref={context.textRef} textAdjustment={context.textAdjustment}>
- {this.props.children}
- </PrivateLabel>
- )}
- </ButtonContext.Consumer>
- );
- }
+export function Label(props: ILabelProps) {
+ const { textAdjustment, textRef } = useContext(ButtonContext);
+ return (
+ <StyledLabelContainer ref={textRef} textAdjustment={textAdjustment}>
+ <StyledLabel>{props.children}</StyledLabel>
+ </StyledLabelContainer>
+ );
}
interface IIconProps {
@@ -59,100 +34,74 @@ interface IIconProps {
height?: number;
}
-export class Icon extends Component<IIconProps> {
- public render() {
- return (
- <ImageView
- source={this.props.source}
- width={this.props.width}
- height={this.props.height}
- tintColor={colors.white}
- />
- );
- }
+export function Icon(props: IIconProps) {
+ return <ImageView {...props} tintColor={colors.white} />;
}
-interface IProps {
+export interface IProps {
children?: React.ReactNode;
- style?: Types.StyleRuleSetRecursive<Types.ButtonStyleRuleSet>;
+ className?: string;
disabled?: boolean;
- onPress?: () => void;
+ onClick?: () => void;
textOffset?: number;
}
interface IState {
- hovered: boolean;
textAdjustment: number;
}
-class BaseButton extends Component<IProps, IState> {
+class BaseButton extends React.Component<IProps, IState> {
public state: IState = {
- hovered: false,
textAdjustment: 0,
};
- private containerRef = React.createRef<View>();
- private textViewRef = React.createRef<PrivateLabel>();
+ private buttonRef = React.createRef<HTMLButtonElement>();
+ private textRef = React.createRef<HTMLDivElement>();
public componentDidMount() {
- consumePromise(this.forceUpdateTextAdjustment());
+ this.updateTextAdjustment();
}
- public render() {
- const { children, style, ...otherProps } = this.props;
+ public componentDidUpdate() {
+ this.updateTextAdjustment();
+ }
+ public render() {
return (
<ButtonContext.Provider
value={{
textAdjustment: this.state.textAdjustment,
- textRef: this.textViewRef,
+ textRef: this.textRef,
}}>
- <Button
- {...otherProps}
- style={[styles.common, this.backgroundStyle(), style]}
- onHoverStart={this.onHoverStart}
- onHoverEnd={this.onHoverEnd}>
- <View style={styles.content} ref={this.containerRef} onLayout={this.onLayout}>
- {React.Children.map(children, (child) =>
+ <StyledButton
+ ref={this.buttonRef}
+ disabled={this.props.disabled}
+ onClick={this.props.onClick}
+ className={this.props.className}>
+ <StyledButtonContent>
+ {React.Children.map(this.props.children, (child) =>
typeof child === 'string' ? <Label>{child as string}</Label> : child,
)}
- </View>
- </Button>
+ </StyledButtonContent>
+ </StyledButton>
</ButtonContext.Provider>
);
}
- protected backgroundStyle = (): Types.ButtonStyleRuleSet => {
- throw new Error('Implement backgroundStyle in subclasses.');
- };
- protected onHoverStart = () => (!this.props.disabled ? this.setState({ hovered: true }) : null);
- protected onHoverEnd = () => (!this.props.disabled ? this.setState({ hovered: false }) : null);
-
- private async forceUpdateTextAdjustment() {
- const containerView = this.containerRef.current;
- if (containerView) {
- const containerLayout = await UserInterface.measureLayoutRelativeToAncestor(
- containerView,
- this,
- );
+ private updateTextAdjustment() {
+ const textOffset = this.props.textOffset ?? 0;
- await this.updateTextAdjustment(containerLayout);
- }
- }
-
- private async updateTextAdjustment(containerLayout: Types.LayoutInfo) {
- const textOffset = this.props.textOffset || 0;
- const labelView = this.textViewRef.current;
+ const buttonRect = this.buttonRef.current?.getBoundingClientRect();
+ const textRect = this.textRef.current?.getBoundingClientRect();
- if (labelView) {
- // calculate the title layout frame
- const labelLayout = await UserInterface.measureLayoutRelativeToAncestor(labelView, this);
+ if (buttonRect && textRect) {
+ const leftDiff = textRect.left - buttonRect.left;
// calculate the remaining space at the right hand side
- const trailingSpace = containerLayout.width - (labelLayout.x + labelLayout.width);
+ const trailingSpace = buttonRect.width - (leftDiff + textRect.width);
// calculate text adjustment
- const textAdjustment = labelLayout.x - trailingSpace - textOffset;
+ const textAdjustment = leftDiff - trailingSpace - textOffset;
// re-render the view with the new text adjustment if it changed
if (this.state.textAdjustment !== textAdjustment) {
@@ -160,10 +109,6 @@ class BaseButton extends Component<IProps, IState> {
}
}
}
-
- private onLayout = (containerLayout: Types.ViewOnLayoutEvent) => {
- consumePromise(this.updateTextAdjustment(containerLayout));
- };
}
interface IBlockingState {
@@ -172,11 +117,11 @@ interface IBlockingState {
interface IBlockingProps {
children?: React.ReactNode;
- onPress: () => Promise<void>;
+ onClick: () => Promise<void>;
disabled?: boolean;
}
-export class BlockingButton extends Component<IBlockingProps, IBlockingState> {
+export class BlockingButton extends React.Component<IBlockingProps, IBlockingState> {
public state = {
isBlocked: false,
};
@@ -187,7 +132,7 @@ export class BlockingButton extends Component<IBlockingProps, IBlockingState> {
return React.cloneElement(child as React.ReactElement, {
...child.props,
disabled: this.state.isBlocked || this.props.disabled,
- onPress: this.onPress,
+ onClick: this.onClick,
});
} else {
return child;
@@ -195,36 +140,49 @@ export class BlockingButton extends Component<IBlockingProps, IBlockingState> {
});
}
- private onPress = () => {
+ private onClick = () => {
this.setState({ isBlocked: true }, async () => {
try {
- await this.props.onPress();
+ await this.props.onClick();
} catch (error) {
- log.error(`onPress() failed - ${error}`);
+ log.error(`onClick() failed - ${error}`);
}
this.setState({ isBlocked: false });
});
};
}
-export class RedButton extends BaseButton {
- protected backgroundStyle = () => (this.state.hovered ? styles.redHover : styles.red);
-}
+export const RedButton = styled(BaseButton)({
+ backgroundColor: colors.red,
+ ':not(:disabled):hover': {
+ backgroundColor: colors.red95,
+ },
+});
-export class GreenButton extends BaseButton {
- protected backgroundStyle = () => (this.state.hovered ? styles.greenHover : styles.green);
-}
+export const GreenButton = styled(BaseButton)({
+ backgroundColor: colors.green,
+ ':not(:disabled):hover': {
+ backgroundColor: colors.green90,
+ },
+});
-export class BlueButton extends BaseButton {
- protected backgroundStyle = () => (this.state.hovered ? styles.blueHover : styles.blue);
-}
+export const BlueButton = styled(BaseButton)({
+ backgroundColor: colors.blue80,
+ ':not(:disabled):hover': {
+ backgroundColor: colors.blue60,
+ },
+});
-export class TransparentButton extends BaseButton {
- protected backgroundStyle = () =>
- this.state.hovered ? styles.transparentHover : styles.transparent;
-}
+export const TransparentButton = styled(BaseButton)({
+ backgroundColor: colors.white20,
+ ':not(:disabled):hover': {
+ backgroundColor: colors.white40,
+ },
+});
-export class RedTransparentButton extends BaseButton {
- protected backgroundStyle = () =>
- this.state.hovered ? styles.redTransparentHover : styles.redTransparent;
-}
+export const RedTransparentButton = styled(BaseButton)({
+ backgroundColor: colors.red60,
+ ':not(:disabled):hover': {
+ backgroundColor: colors.red80,
+ },
+});
diff --git a/gui/src/renderer/components/AppButtonStyles.tsx b/gui/src/renderer/components/AppButtonStyles.tsx
index e9594e3994..e8100ca82c 100644
--- a/gui/src/renderer/components/AppButtonStyles.tsx
+++ b/gui/src/renderer/components/AppButtonStyles.tsx
@@ -1,57 +1,39 @@
-import { Styles } from 'reactxp';
+import styled from 'styled-components';
import { colors } from '../../config.json';
-export default {
- red: Styles.createButtonStyle({
- backgroundColor: colors.red,
- }),
- redHover: Styles.createButtonStyle({
- backgroundColor: colors.red95,
- }),
- green: Styles.createButtonStyle({
- backgroundColor: colors.green,
- }),
- greenHover: Styles.createButtonStyle({
- backgroundColor: colors.green90,
- }),
- blue: Styles.createButtonStyle({
- backgroundColor: colors.blue80,
- }),
- blueHover: Styles.createButtonStyle({
- backgroundColor: colors.blue60,
- }),
- transparent: Styles.createButtonStyle({
- backgroundColor: colors.white20,
- }),
- transparentHover: Styles.createButtonStyle({
- backgroundColor: colors.white40,
- }),
- redTransparent: Styles.createButtonStyle({
- backgroundColor: colors.red60,
- }),
- redTransparentHover: Styles.createButtonStyle({
- backgroundColor: colors.red80,
- }),
- common: Styles.createViewStyle({
- cursor: 'default',
- borderRadius: 4,
- }),
- content: Styles.createViewStyle({
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- padding: 9,
- }),
- labelContainer: Styles.createViewStyle({
- flex: 1,
- }),
- label: Styles.createTextStyle({
- fontFamily: 'DINPro',
- fontSize: 20,
- fontWeight: '900',
- lineHeight: 26,
- flex: 1,
- color: colors.white,
- textAlign: 'center',
- }),
-};
+export const StyledLabelContainer = styled.div((props: { textAdjustment: number }) => ({
+ display: 'flex',
+ flex: 1,
+ paddingRight: `${props.textAdjustment > 0 ? props.textAdjustment : 0}px`,
+ paddingLeft: `${props.textAdjustment < 0 ? Math.abs(props.textAdjustment) : 0}px`,
+}));
+
+export const StyledLabel = styled.span({
+ fontFamily: 'DINPro',
+ fontSize: '20px',
+ fontWeight: 900,
+ lineHeight: '26px',
+ flex: 1,
+ color: colors.white,
+ textAlign: 'center',
+});
+
+export const StyledButton = styled.button({
+ display: 'flex',
+ cursor: 'default',
+ borderRadius: 4,
+ border: 'none',
+ padding: 0,
+ ':disabled': {
+ opacity: 0.5,
+ },
+});
+
+export const StyledButtonContent = styled.div({
+ display: 'flex',
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 9,
+});
diff --git a/gui/src/renderer/components/ExpiredAccountErrorView.tsx b/gui/src/renderer/components/ExpiredAccountErrorView.tsx
index 55adb81a82..61140016ea 100644
--- a/gui/src/renderer/components/ExpiredAccountErrorView.tsx
+++ b/gui/src/renderer/components/ExpiredAccountErrorView.tsx
@@ -12,6 +12,8 @@ import CustomScrollbars from './CustomScrollbars';
import styles, {
ModalCellContainer,
StyledAccountTokenLabel,
+ StyledBuyCreditButton,
+ StyledDisconnectButton,
} from './ExpiredAccountErrorViewStyles';
import ImageView from './ImageView';
import { ModalAlert, ModalAlertType, ModalMessage } from './Modal';
@@ -63,10 +65,10 @@ export default class ExpiredAccountErrorView extends Component<
<View style={styles.footer}>
{this.getRecoveryAction() === RecoveryAction.disconnect && (
- <AppButton.BlockingButton onPress={this.props.onDisconnect}>
- <AppButton.RedButton style={styles.button}>
+ <AppButton.BlockingButton onClick={this.props.onDisconnect}>
+ <StyledDisconnectButton>
{messages.pgettext('connect-view', 'Disconnect')}
- </AppButton.RedButton>
+ </StyledDisconnectButton>
</AppButton.BlockingButton>
)}
@@ -74,7 +76,7 @@ export default class ExpiredAccountErrorView extends Component<
<AppButton.GreenButton
disabled={this.getRecoveryAction() === RecoveryAction.disconnect}
- onPress={this.onOpenRedeemVoucherAlert}>
+ onClick={this.onOpenRedeemVoucherAlert}>
{messages.pgettext('connect-view', 'Redeem voucher')}
</AppButton.GreenButton>
</View>
@@ -160,11 +162,11 @@ export default class ExpiredAccountErrorView extends Component<
return (
<AppButton.BlockingButton
disabled={this.getRecoveryAction() === RecoveryAction.disconnect}
- onPress={this.onOpenExternalPayment}>
- <AppButton.GreenButton style={styles.button}>
+ onClick={this.onOpenExternalPayment}>
+ <StyledBuyCreditButton>
<AppButton.Label>{buttonText}</AppButton.Label>
<AppButton.Icon source="icon-extLink" height={16} width={16} />
- </AppButton.GreenButton>
+ </StyledBuyCreditButton>
</AppButton.BlockingButton>
);
}
@@ -184,7 +186,7 @@ export default class ExpiredAccountErrorView extends Component<
buttons={[
<AppButton.BlueButton
key="cancel"
- onPress={this.onCloseBlockWhenDisconnectedInstructions}>
+ onClick={this.onCloseBlockWhenDisconnectedInstructions}>
{messages.gettext('Close')}
</AppButton.BlueButton>,
]}>
diff --git a/gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx b/gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx
index 352a29db78..a8049095c3 100644
--- a/gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx
+++ b/gui/src/renderer/components/ExpiredAccountErrorViewStyles.tsx
@@ -2,6 +2,7 @@ import { Styles } from 'reactxp';
import styled from 'styled-components';
import { colors } from '../../config.json';
import AccountTokenLabel from './AccountTokenLabel';
+import * as AppButton from './AppButton';
import * as Cell from './Cell';
export const StyledAccountTokenLabel = styled(AccountTokenLabel)({
@@ -16,6 +17,13 @@ export const ModalCellContainer = styled(Cell.Container)({
marginTop: '16px',
});
+const buttonStyle = {
+ marginBottom: 24,
+};
+
+export const StyledBuyCreditButton = styled(AppButton.GreenButton)(buttonStyle);
+export const StyledDisconnectButton = styled(AppButton.RedButton)(buttonStyle);
+
export default {
// plain CSS style
scrollview: {
@@ -79,7 +87,4 @@ export default {
height: 68,
justifyContent: 'center',
}),
- button: Styles.createViewStyle({
- marginBottom: 24,
- }),
};
diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx
index 9d317091ac..f22f72be67 100644
--- a/gui/src/renderer/components/Login.tsx
+++ b/gui/src/renderer/components/Login.tsx
@@ -400,7 +400,7 @@ export default class Login extends Component<IProps, IState> {
{messages.pgettext('login-view', "Don't have an account number?")}
</Text>
<AppButton.BlueButton
- onPress={this.props.createNewAccount}
+ onClick={this.props.createNewAccount}
disabled={!this.allowInteraction()}>
{messages.pgettext('login-view', 'Create account')}
</AppButton.BlueButton>
diff --git a/gui/src/renderer/components/MultiButton.tsx b/gui/src/renderer/components/MultiButton.tsx
index efd21ee9ca..a9f1d09dee 100644
--- a/gui/src/renderer/components/MultiButton.tsx
+++ b/gui/src/renderer/components/MultiButton.tsx
@@ -1,49 +1,40 @@
-import * as React from 'react';
-import { Component, Styles, Types, View } from 'reactxp';
+import React from 'react';
+import styled from 'styled-components';
+import * as AppButton from './AppButton';
const SIDE_BUTTON_WIDTH = 50;
-const styles = {
- buttonRow: Styles.createViewStyle({
- flexDirection: 'row',
- }),
- mainButton: Styles.createViewStyle({
- flex: 1,
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- }),
- sideButton: Styles.createViewStyle({
- borderTopLeftRadius: 0,
- borderBottomLeftRadius: 0,
- width: SIDE_BUTTON_WIDTH,
- alignItems: 'center',
- marginLeft: 1,
- }),
-};
+const ButtonRow = styled.div({
+ display: 'flex',
+ flexDirection: 'row',
+});
-interface IProps {
- mainButton: React.ComponentType<IMainButtonProps>;
- sideButton: React.ComponentType<ISideButtonProps>;
-}
+const MainButton = styled.button({
+ display: 'flex',
+ flex: 1,
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+});
-export interface IMainButtonProps {
- textOffset: number;
- style?: Types.StyleRuleSetRecursive<Types.ViewStyleRuleSet>;
-}
+const SideButton = styled.button({
+ display: 'flex',
+ borderTopLeftRadius: 0,
+ borderBottomLeftRadius: 0,
+ width: SIDE_BUTTON_WIDTH,
+ alignItems: 'center',
+ marginLeft: 1,
+});
-export interface ISideButtonProps {
- style?: Types.StyleRuleSetRecursive<Types.ViewStyleRuleSet>;
+interface IMultiButtonProps {
+ mainButton: React.ComponentType<AppButton.IProps>;
+ sideButton: React.ComponentType<AppButton.IProps>;
}
-export class MultiButton extends Component<IProps> {
- public render() {
- const { mainButton: MainButton, sideButton: SideButton } = this.props;
-
- return (
- <View style={styles.buttonRow}>
- <MainButton textOffset={SIDE_BUTTON_WIDTH} style={styles.mainButton} />
- <SideButton style={styles.sideButton} />
- </View>
- );
- }
+export function MultiButton(props: IMultiButtonProps) {
+ return (
+ <ButtonRow>
+ <MainButton as={props.mainButton} textOffset={SIDE_BUTTON_WIDTH} />
+ <SideButton as={props.sideButton} />
+ </ButtonRow>
+ );
}
diff --git a/gui/src/renderer/components/NotificationBanner.tsx b/gui/src/renderer/components/NotificationBanner.tsx
index 360c910403..5831676fcf 100644
--- a/gui/src/renderer/components/NotificationBanner.tsx
+++ b/gui/src/renderer/components/NotificationBanner.tsx
@@ -105,7 +105,7 @@ export class NotificationOpenLinkAction extends Component<INotifcationOpenLinkAc
public render() {
return (
- <BlockingButton onPress={this.props.onPress}>
+ <BlockingButton onClick={this.props.onPress}>
<Button
style={styles.actionButton}
onHoverStart={this.onHoverStart}
diff --git a/gui/src/renderer/components/RedeemVoucher.tsx b/gui/src/renderer/components/RedeemVoucher.tsx
index da7a398bb0..4fdb57b64e 100644
--- a/gui/src/renderer/components/RedeemVoucher.tsx
+++ b/gui/src/renderer/components/RedeemVoucher.tsx
@@ -1,6 +1,5 @@
import React, { useCallback, useContext, useState } from 'react';
import { useSelector } from 'react-redux';
-import { Types } from 'reactxp';
import { VoucherResponse } from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
import { useScheduler } from '../../shared/scheduler';
@@ -178,7 +177,7 @@ export function RedeemVoucherSubmitButton() {
const disabled = submitting || response?.type === 'success';
return (
- <AppButton.GreenButton key="cancel" disabled={!valueValid || disabled} onPress={onSubmit}>
+ <AppButton.GreenButton key="cancel" disabled={!valueValid || disabled} onClick={onSubmit}>
{messages.pgettext('redeem-voucher-view', 'Redeem')}
</AppButton.GreenButton>
);
@@ -196,7 +195,7 @@ export function RedeemVoucherAlert(props: IRedeemVoucherAlertProps) {
<ModalAlert
buttons={[
<RedeemVoucherSubmitButton key="submit" />,
- <AppButton.BlueButton key="cancel" disabled={cancelDisabled} onPress={props.onClose}>
+ <AppButton.BlueButton key="cancel" disabled={cancelDisabled} onClick={props.onClose}>
{messages.pgettext('redeem-voucher-alert', 'Cancel')}
</AppButton.BlueButton>,
]}>
@@ -208,19 +207,19 @@ export function RedeemVoucherAlert(props: IRedeemVoucherAlertProps) {
}
interface IRedeemVoucherButtonProps {
- style?: Types.StyleRuleSetRecursive<Types.ViewStyleRuleSet>;
+ className?: string;
}
export function RedeemVoucherButton(props: IRedeemVoucherButtonProps) {
const isBlocked = useSelector((state: IReduxState) => state.connection.isBlocked);
const [showAlert, setShowAlert] = useState(false);
- const onPress = useCallback(() => setShowAlert(true), []);
+ const onClick = useCallback(() => setShowAlert(true), []);
const onClose = useCallback(() => setShowAlert(false), []);
return (
<>
- <AppButton.GreenButton disabled={isBlocked} onPress={onPress} style={props.style}>
+ <AppButton.GreenButton disabled={isBlocked} onClick={onClick} className={props.className}>
{messages.pgettext('redeem-voucher-alert', 'Redeem voucher')}
</AppButton.GreenButton>
{showAlert && (
diff --git a/gui/src/renderer/components/Settings.tsx b/gui/src/renderer/components/Settings.tsx
index 644190a4db..4a7684f405 100644
--- a/gui/src/renderer/components/Settings.tsx
+++ b/gui/src/renderer/components/Settings.tsx
@@ -89,7 +89,7 @@ export default class Settings extends Component<IProps> {
private renderQuitButton() {
return (
<View style={styles.quitButtonFooter}>
- <AppButton.RedButton onPress={this.props.onQuit}>
+ <AppButton.RedButton onClick={this.props.onQuit}>
{messages.pgettext('settings-view', 'Quit app')}
</AppButton.RedButton>
</View>
diff --git a/gui/src/renderer/components/Support.tsx b/gui/src/renderer/components/Support.tsx
index 244f939a5e..ee0514e67f 100644
--- a/gui/src/renderer/components/Support.tsx
+++ b/gui/src/renderer/components/Support.tsx
@@ -8,7 +8,7 @@ import { Container, Layout } from './Layout';
import { ModalAlert, ModalAlertType, ModalContainer } from './Modal';
import { BackBarItem, NavigationBar, NavigationItems } from './NavigationBar';
import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader';
-import styles from './SupportStyles';
+import styles, { StyledBlueButton } from './SupportStyles';
import { AccountToken } from '../../shared/daemon-rpc-types';
import { ISupportReportForm } from '../redux/support/actions';
@@ -231,10 +231,10 @@ export default class Support extends Component<ISupportProps, ISupportState> {
type={ModalAlertType.Warning}
message={message}
buttons={[
- <AppButton.RedButton key="proceed" onPress={this.onSend}>
+ <AppButton.RedButton key="proceed" onClick={this.onSend}>
{messages.pgettext('support-view', 'Send anyway')}
</AppButton.RedButton>,
- <AppButton.BlueButton key="cancel" onPress={this.onCancelNoEmailDialog}>
+ <AppButton.BlueButton key="cancel" onClick={this.onCancelNoEmailDialog}>
{messages.gettext('Back')}
</AppButton.BlueButton>,
]}
@@ -261,14 +261,14 @@ export default class Support extends Component<ISupportProps, ISupportState> {
<AppButton.GreenButton
key="upgrade"
disabled={this.props.isOffline}
- onPress={this.openDownloadLink}>
+ onClick={this.openDownloadLink}>
<AppButton.Label>{messages.pgettext('support-view', 'Upgrade app')}</AppButton.Label>
<AppButton.Icon height={16} width={16} source="icon-extLink" />
</AppButton.GreenButton>,
- <AppButton.RedButton key="proceed" onPress={this.acknowledgeOutdateVersion}>
+ <AppButton.RedButton key="proceed" onClick={this.acknowledgeOutdateVersion}>
{messages.pgettext('support-view', 'Continue anyway')}
</AppButton.RedButton>,
- <AppButton.BlueButton key="cancel" onPress={this.props.onClose}>
+ <AppButton.BlueButton key="cancel" onClick={this.props.onClose}>
{messages.gettext('Cancel')}
</AppButton.BlueButton>,
]}
@@ -301,18 +301,15 @@ export default class Support extends Component<ISupportProps, ISupportState> {
</View>
</View>
<View style={styles.support__footer}>
- <AppButton.BlueButton
- style={styles.view_logs_button}
- onPress={this.onViewLog}
- disabled={this.state.disableActions}>
+ <StyledBlueButton onClick={this.onViewLog} disabled={this.state.disableActions}>
<AppButton.Label>
{messages.pgettext('support-view', 'View app logs')}
</AppButton.Label>
<AppButton.Icon source="icon-extLink" height={16} width={16} />
- </AppButton.BlueButton>
+ </StyledBlueButton>
<AppButton.GreenButton
disabled={!this.validate() || this.state.disableActions}
- onPress={this.onSend}>
+ onClick={this.onSend}>
{messages.pgettext('support-view', 'Send')}
</AppButton.GreenButton>
</View>
@@ -406,10 +403,10 @@ export default class Support extends Component<ISupportProps, ISupportState> {
</View>
</View>
<View style={styles.support__footer}>
- <AppButton.BlueButton style={styles.edit_message_button} onPress={this.handleEditMessage}>
+ <StyledBlueButton onClick={this.handleEditMessage}>
{messages.pgettext('support-view', 'Edit message')}
- </AppButton.BlueButton>
- <AppButton.GreenButton onPress={this.onSend}>
+ </StyledBlueButton>
+ <AppButton.GreenButton onClick={this.onSend}>
{messages.pgettext('support-view', 'Try again')}
</AppButton.GreenButton>
</View>
diff --git a/gui/src/renderer/components/SupportStyles.tsx b/gui/src/renderer/components/SupportStyles.tsx
index d883c806ba..5c5915bcd4 100644
--- a/gui/src/renderer/components/SupportStyles.tsx
+++ b/gui/src/renderer/components/SupportStyles.tsx
@@ -1,5 +1,11 @@
import { Styles } from 'reactxp';
+import styled from 'styled-components';
import { colors } from '../../config.json';
+import * as AppButton from './AppButton';
+
+export const StyledBlueButton = styled(AppButton.BlueButton)({
+ marginBottom: 16,
+});
export default {
support: Styles.createViewStyle({
@@ -51,12 +57,6 @@ export default {
alignItems: 'center',
marginBottom: 32,
}),
- view_logs_button: Styles.createViewStyle({
- marginBottom: 16,
- }),
- edit_message_button: Styles.createViewStyle({
- marginBottom: 16,
- }),
support__form_email: Styles.createTextStyle({
flex: 1,
borderRadius: 4,
diff --git a/gui/src/renderer/components/TunnelControl.tsx b/gui/src/renderer/components/TunnelControl.tsx
index bb2c06ef62..7043c900c8 100644
--- a/gui/src/renderer/components/TunnelControl.tsx
+++ b/gui/src/renderer/components/TunnelControl.tsx
@@ -1,5 +1,6 @@
import * as React from 'react';
import { Component, Styles, Types, View } from 'reactxp';
+import styled from 'styled-components';
import { colors } from '../../config.json';
import { TunnelState } from '../../shared/daemon-rpc-types';
import { messages } from '../../shared/gettext';
@@ -7,7 +8,7 @@ import ConnectionPanelContainer from '../containers/ConnectionPanelContainer';
import * as AppButton from './AppButton';
import ImageView from './ImageView';
import Marquee from './Marquee';
-import { IMainButtonProps, ISideButtonProps, MultiButton } from './MultiButton';
+import { MultiButton } from './MultiButton';
import SecuredLabel, { SecuredDisplayStyle } from './SecuredLabel';
interface ITunnelControlProps {
@@ -21,6 +22,10 @@ interface ITunnelControlProps {
onSelectLocation: () => void;
}
+const SwitchLocationButton = styled(AppButton.TransparentButton)({
+ marginBottom: 16,
+});
+
const styles = {
body: Styles.createViewStyle({
paddingTop: 0,
@@ -39,9 +44,6 @@ const styles = {
wrapper: Styles.createViewStyle({
flex: 1,
}),
- switch_location_button: Styles.createViewStyle({
- marginBottom: 16,
- }),
status_security: Styles.createTextStyle({
fontFamily: 'Open Sans',
fontSize: 16,
@@ -76,49 +78,45 @@ export default class TunnelControl extends Component<ITunnelControlProps> {
const SwitchLocation = () => {
return (
- <AppButton.TransparentButton
- style={styles.switch_location_button}
- onPress={this.props.onSelectLocation}>
+ <SwitchLocationButton onClick={this.props.onSelectLocation}>
{messages.pgettext('tunnel-control', 'Switch location')}
- </AppButton.TransparentButton>
+ </SwitchLocationButton>
);
};
const SelectedLocation = () => (
- <AppButton.TransparentButton
- style={styles.switch_location_button}
- onPress={this.props.onSelectLocation}>
+ <SwitchLocationButton onClick={this.props.onSelectLocation}>
<AppButton.Label>{this.props.selectedRelayName}</AppButton.Label>
<AppButton.Icon height={12} width={7} source="icon-chevron" />
- </AppButton.TransparentButton>
+ </SwitchLocationButton>
);
const Connect = () => (
- <AppButton.GreenButton onPress={this.props.onConnect}>
+ <AppButton.GreenButton onClick={this.props.onConnect}>
{messages.pgettext('tunnel-control', 'Secure my connection')}
</AppButton.GreenButton>
);
- const Disconnect = (props: IMainButtonProps) => (
- <AppButton.RedTransparentButton onPress={this.props.onDisconnect} {...props}>
+ const Disconnect = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => (
+ <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
{messages.pgettext('tunnel-control', 'Disconnect')}
</AppButton.RedTransparentButton>
);
- const Cancel = (props: IMainButtonProps) => (
- <AppButton.RedTransparentButton onPress={this.props.onDisconnect} {...props}>
+ const Cancel = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => (
+ <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
{messages.pgettext('tunnel-control', 'Cancel')}
</AppButton.RedTransparentButton>
);
- const Dismiss = (props: IMainButtonProps) => (
- <AppButton.RedTransparentButton onPress={this.props.onDisconnect} {...props}>
+ const Dismiss = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => (
+ <AppButton.RedTransparentButton onClick={this.props.onDisconnect} {...props}>
{messages.pgettext('tunnel-control', 'Dismiss')}
</AppButton.RedTransparentButton>
);
- const Reconnect = (props: ISideButtonProps) => (
- <AppButton.RedTransparentButton onPress={this.props.onReconnect} {...props}>
+ const Reconnect = (props: React.ComponentProps<typeof AppButton.RedTransparentButton>) => (
+ <AppButton.RedTransparentButton onClick={this.props.onReconnect} {...props}>
<ImageView height={22} width={22} source="icon-reload" tintColor="white" />
</AppButton.RedTransparentButton>
);
diff --git a/gui/src/renderer/components/WireguardKeys.tsx b/gui/src/renderer/components/WireguardKeys.tsx
index 5af224be35..b11ffe59c0 100644
--- a/gui/src/renderer/components/WireguardKeys.tsx
+++ b/gui/src/renderer/components/WireguardKeys.tsx
@@ -119,7 +119,7 @@ export default class WireguardKeys extends Component<IProps, IState> {
<View style={styles.wgkeys__row}>
<AppButton.BlueButton
disabled={this.isVerifyButtonDisabled()}
- onPress={this.getOnVerifyKeyCb()}>
+ onClick={this.getOnVerifyKeyCb()}>
<AppButton.Label>
{messages.pgettext('wireguard-key-view', 'Verify key')}
</AppButton.Label>
@@ -128,7 +128,7 @@ export default class WireguardKeys extends Component<IProps, IState> {
<View style={styles.wgkeys__row}>
<AppButton.BlockingButton
disabled={this.props.isOffline}
- onPress={this.props.onVisitWebsiteKey}>
+ onClick={this.props.onVisitWebsiteKey}>
<AppButton.BlueButton>
<AppButton.Label>
{messages.pgettext('wireguard-key-view', 'Manage keys')}
@@ -203,7 +203,7 @@ export default class WireguardKeys extends Component<IProps, IState> {
return this.busyButton(messages.pgettext('wireguard-key-view', 'Generating key'));
}
return (
- <AppButton.GreenButton disabled={this.props.isOffline} onPress={generateKey}>
+ <AppButton.GreenButton disabled={this.props.isOffline} onClick={generateKey}>
<AppButton.Label>{buttonText}</AppButton.Label>
</AppButton.GreenButton>
);