summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2018-10-08 14:25:30 +0200
committerAndrej Mihajlov <and@mullvad.net>2018-10-08 14:25:30 +0200
commitaf6141a0667665a078d1cb90202accaeaca21fef (patch)
tree50a6f77d00cb9f664c003f3d94cc153322b66ff8
parentc16b7bb907227c5bd186c03f49829ddb652815b4 (diff)
parent127a19c557097cddecbda1f6031957736855548a (diff)
downloadmullvadvpn-af6141a0667665a078d1cb90202accaeaca21fef.tar.xz
mullvadvpn-af6141a0667665a078d1cb90202accaeaca21fef.zip
Merge branch 'smart-navigation-title'
-rw-r--r--gui/package.json10
-rw-r--r--gui/packages/desktop/src/config.json1
-rw-r--r--gui/packages/desktop/src/renderer/components/Account.js2
-rw-r--r--gui/packages/desktop/src/renderer/components/AdvancedSettings.js67
-rw-r--r--gui/packages/desktop/src/renderer/components/CustomScrollbars.js28
-rw-r--r--gui/packages/desktop/src/renderer/components/NavigationBar.js303
-rw-r--r--gui/packages/desktop/src/renderer/components/Preferences.js2
-rw-r--r--gui/packages/desktop/src/renderer/components/SelectLocation.js53
-rw-r--r--gui/packages/desktop/src/renderer/components/Settings.js64
-rw-r--r--gui/packages/desktop/src/renderer/components/SettingsHeader.js2
-rw-r--r--gui/packages/desktop/src/renderer/components/Support.js4
-rw-r--r--gui/packages/desktop/test/components/Settings.spec.js2
-rw-r--r--gui/yarn.lock50
13 files changed, 461 insertions, 127 deletions
diff --git a/gui/package.json b/gui/package.json
index c6eed545c5..0439c7d096 100644
--- a/gui/package.json
+++ b/gui/package.json
@@ -17,12 +17,12 @@
"devDependencies": {
"babel-eslint": "^8.2.6",
"eslint": "^5.2.0",
- "eslint-config-prettier": "^2.9.0",
- "eslint-plugin-flowtype": "^2.50.0",
- "eslint-plugin-promise": "^3.8.0",
+ "eslint-config-prettier": "^3.1.0",
+ "eslint-plugin-flowtype": "^2.50.3",
+ "eslint-plugin-promise": "^4.0.1",
"eslint-plugin-react": "^7.10.0",
- "flow-bin": "0.78",
+ "flow-bin": "0.82",
"flow-typed": "^2.5.1",
- "prettier": "1.13.7"
+ "prettier": "1.14.3"
}
}
diff --git a/gui/packages/desktop/src/config.json b/gui/packages/desktop/src/config.json
index f28b2ca3b0..e3f340ec96 100644
--- a/gui/packages/desktop/src/config.json
+++ b/gui/packages/desktop/src/config.json
@@ -3,7 +3,6 @@
"createAccount": "https://mullvad.net/account/create/",
"purchase": "https://mullvad.net/account/login/",
"faq": "https://mullvad.net/faq/",
- "guides": "https://mullvad.net/guides/",
"download": "https://mullvad.net/download/",
"supportEmail": "mailto:support@mullvad.net"
},
diff --git a/gui/packages/desktop/src/renderer/components/Account.js b/gui/packages/desktop/src/renderer/components/Account.js
index 1dbb896bf6..a08165c1bc 100644
--- a/gui/packages/desktop/src/renderer/components/Account.js
+++ b/gui/packages/desktop/src/renderer/components/Account.js
@@ -6,7 +6,7 @@ import { Component, Text, View } from 'reactxp';
import { ClipboardLabel } from '@mullvad/components';
import * as AppButton from './AppButton';
import { Layout, Container } from './Layout';
-import NavigationBar, { BackBarItem } from './NavigationBar';
+import { NavigationBar, BackBarItem } from './NavigationBar';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
import styles from './AccountStyles';
import Img from './Img';
diff --git a/gui/packages/desktop/src/renderer/components/AdvancedSettings.js b/gui/packages/desktop/src/renderer/components/AdvancedSettings.js
index 284867f3ca..e043032e53 100644
--- a/gui/packages/desktop/src/renderer/components/AdvancedSettings.js
+++ b/gui/packages/desktop/src/renderer/components/AdvancedSettings.js
@@ -4,9 +4,14 @@ import * as React from 'react';
import { Button, Component, Text, View } from 'reactxp';
import * as Cell from './Cell';
import { Layout, Container } from './Layout';
-import NavigationBar, { BackBarItem } from './NavigationBar';
+import {
+ NavigationBar,
+ NavigationContainer,
+ NavigationScrollbars,
+ BackBarItem,
+ TitleBarItem,
+} from './NavigationBar';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
-import CustomScrollbars from './CustomScrollbars';
import Switch from './Switch';
import styles from './AdvancedSettingsStyles';
import Img from './Img';
@@ -35,37 +40,41 @@ export class AdvancedSettings extends Component<Props> {
<Layout>
<Container>
<View style={styles.advanced_settings}>
- <NavigationBar>
- <BackBarItem action={this.props.onClose} title={'Settings'} />
- </NavigationBar>
+ <NavigationContainer>
+ <NavigationBar>
+ <BackBarItem action={this.props.onClose} title={'Settings'} />
+ <TitleBarItem>Advanced</TitleBarItem>
+ </NavigationBar>
- <View style={styles.advanced_settings__container}>
- <SettingsHeader>
- <HeaderTitle>Advanced</HeaderTitle>
- </SettingsHeader>
- <CustomScrollbars style={styles.advanced_settings__scrollview}>
- <Cell.Container>
- <Cell.Label>Enable IPv6</Cell.Label>
- <Switch isOn={this.props.enableIpv6} onChange={this.props.setEnableIpv6} />
- </Cell.Container>
- <Cell.Footer>Enable IPv6 communication through the tunnel.</Cell.Footer>
+ <View style={styles.advanced_settings__container}>
+ <NavigationScrollbars style={styles.advanced_settings__scrollview}>
+ <SettingsHeader>
+ <HeaderTitle>Advanced</HeaderTitle>
+ </SettingsHeader>
- <View style={styles.advanced_settings__content}>
- <Selector
- title={'Network protocols'}
- values={['Automatic', 'UDP', 'TCP']}
- value={protocol}
- onSelect={(protocol) => {
- this.props.onUpdate(protocol, 'Automatic');
- }}
- />
+ <Cell.Container>
+ <Cell.Label>Enable IPv6</Cell.Label>
+ <Switch isOn={this.props.enableIpv6} onChange={this.props.setEnableIpv6} />
+ </Cell.Container>
+ <Cell.Footer>Enable IPv6 communication through the tunnel.</Cell.Footer>
- <View style={styles.advanced_settings__cell_spacer} />
+ <View style={styles.advanced_settings__content}>
+ <Selector
+ title={'Network protocols'}
+ values={['Automatic', 'UDP', 'TCP']}
+ value={protocol}
+ onSelect={(protocol) => {
+ this.props.onUpdate(protocol, 'Automatic');
+ }}
+ />
- {portSelector}
- </View>
- </CustomScrollbars>
- </View>
+ <View style={styles.advanced_settings__cell_spacer} />
+
+ {portSelector}
+ </View>
+ </NavigationScrollbars>
+ </View>
+ </NavigationContainer>
</View>
</Container>
</Layout>
diff --git a/gui/packages/desktop/src/renderer/components/CustomScrollbars.js b/gui/packages/desktop/src/renderer/components/CustomScrollbars.js
index 9754c2d364..c6e5c09afe 100644
--- a/gui/packages/desktop/src/renderer/components/CustomScrollbars.js
+++ b/gui/packages/desktop/src/renderer/components/CustomScrollbars.js
@@ -12,6 +12,7 @@ const AUTOHIDE_TIMEOUT = 1000;
type Props = {
autoHide: boolean,
trackPadding: { x: number, y: number },
+ onScroll?: ({ scrollLeft: number, scrollTop: number }) => void,
children?: React.Node,
};
@@ -91,6 +92,24 @@ export default class CustomScrollbars extends React.Component<Props, State> {
}
}
+ shouldComponentUpdate(nextProps: Props, nextState: State) {
+ const prevProps = this.props;
+ const prevState = this.state;
+
+ return (
+ prevProps.children !== nextProps.children ||
+ prevProps.autoHide !== nextProps.autoHide ||
+ prevProps.trackPadding.x !== nextProps.trackPadding.x ||
+ prevProps.trackPadding.y !== nextProps.trackPadding.y ||
+ prevState.canScroll !== nextState.canScroll ||
+ prevState.showScrollIndicators !== nextState.showScrollIndicators ||
+ prevState.showTrack !== nextState.showTrack ||
+ prevState.isTrackHovered !== nextState.isTrackHovered ||
+ prevState.isDragging !== nextState.isDragging ||
+ prevState.isWide !== nextState.isWide
+ );
+ }
+
componentWillUnmount() {
this._stopAutoHide();
@@ -222,6 +241,7 @@ export default class CustomScrollbars extends React.Component<Props, State> {
const {
autoHide: _autoHide,
trackPadding: _trackPadding,
+ onScroll: _onScroll,
children,
...otherProps
} = this.props;
@@ -268,6 +288,14 @@ export default class CustomScrollbars extends React.Component<Props, State> {
this._startAutoShrink();
}
}
+
+ const scrollView = this._scrollableRef.current;
+ if (scrollView && this.props.onScroll) {
+ this.props.onScroll({
+ scrollLeft: scrollView.scrollLeft,
+ scrollTop: scrollView.scrollTop,
+ });
+ }
};
_ensureScrollbarsVisible() {
diff --git a/gui/packages/desktop/src/renderer/components/NavigationBar.js b/gui/packages/desktop/src/renderer/components/NavigationBar.js
index 996e0e622b..7c603ea68b 100644
--- a/gui/packages/desktop/src/renderer/components/NavigationBar.js
+++ b/gui/packages/desktop/src/renderer/components/NavigationBar.js
@@ -1,16 +1,23 @@
// @flow
import * as React from 'react';
-import { Button, Component, Text, View, Styles } from 'reactxp';
+import { Animated, Button, Component, Text, View, Styles, UserInterface } from 'reactxp';
import Img from './Img';
+import CustomScrollbars from './CustomScrollbars';
import { colors } from '../../config';
const styles = {
navigationBar: {
default: Styles.createViewStyle({
flex: 0,
- alignItems: 'flex-start',
- paddingLeft: 12,
+ flexDirection: 'row',
+ paddingHorizontal: 12,
+ paddingBottom: 12,
+ }),
+ separator: Styles.createViewStyle({
+ borderStyle: 'solid',
+ borderBottomWidth: 1,
+ borderColor: 'rgba(0, 0, 0, 0.2)',
}),
darwin: Styles.createViewStyle({
paddingTop: 24,
@@ -23,6 +30,21 @@ const styles = {
WebkitAppRegion: 'drag',
}),
},
+ navigationBarTitle: {
+ container: Styles.createViewStyle({
+ flex: 1,
+ flexDirection: 'column',
+ justifyContent: 'center',
+ }),
+ label: Styles.createTextStyle({
+ fontFamily: 'Open Sans',
+ fontSize: 16,
+ fontWeight: '600',
+ lineHeight: 22,
+ color: colors.white60,
+ alignSelf: 'center',
+ }),
+ },
closeBarItem: {
default: Styles.createViewStyle({
cursor: 'default',
@@ -58,16 +80,287 @@ const styles = {
},
};
-export default class NavigationBar extends Component {
+const NavigationScrollContext = React.createContext({
+ scrollTop: 0,
+ onScroll: (_scroll) => {},
+});
+
+export class NavigationContainer extends Component {
+ state = {
+ scrollTop: 0,
+ };
+
+ _onScroll = (scroll) => {
+ this.setState({
+ scrollTop: scroll.scrollTop,
+ });
+ };
+
render() {
return (
- <View style={[styles.navigationBar.default, styles.navigationBar[process.platform]]}>
+ <NavigationScrollContext.Provider
+ value={{ scrollTop: this.state.scrollTop, onScroll: this._onScroll }}>
{this.props.children}
+ </NavigationScrollContext.Provider>
+ );
+ }
+}
+
+/* $FlowFixMe: React.forwardRef is not supported yet by Flow.
+ See: https://github.com/facebook/flow/issues/6103 */
+export const NavigationScrollbars = React.forwardRef(function NavigationScrollbars(
+ props: React.ElementProps<typeof CustomScrollbars>,
+ ref,
+) {
+ return (
+ <NavigationScrollContext.Consumer>
+ {(context) => {
+ const { children, ...otherProps } = props;
+ const wrappedOnScroll = (scroll) => {
+ context.onScroll(scroll);
+
+ if (otherProps.onScroll) {
+ otherProps.onScroll(scroll);
+ }
+ };
+
+ return (
+ <CustomScrollbars {...otherProps} ref={ref} onScroll={wrappedOnScroll}>
+ {children}
+ </CustomScrollbars>
+ );
+ }}
+ </NavigationScrollContext.Consumer>
+ );
+});
+
+type PrivateTitleBarItemProps = {
+ visible: boolean,
+ titleAdjustment: number,
+ children?: React.Node,
+};
+
+class PrivateTitleBarItem extends Component<PrivateTitleBarItemProps> {
+ shouldComponentUpdate(nextProps: PrivateTitleBarItemProps) {
+ return (
+ this.props.visible !== nextProps.visible ||
+ this.props.titleAdjustment !== nextProps.titleAdjustment ||
+ this.props.children !== nextProps.children
+ );
+ }
+
+ render() {
+ const titleAdjustment = this.props.titleAdjustment;
+ const titleAdjustmentStyle = Styles.createViewStyle(
+ {
+ paddingRight: titleAdjustment > 0 ? titleAdjustment : 0,
+ paddingLeft: titleAdjustment < 0 ? Math.abs(titleAdjustment) : 0,
+ },
+ false,
+ );
+
+ return (
+ <View style={[styles.navigationBarTitle.container, titleAdjustmentStyle]}>
+ <PrivateBarItemAnimationContainer visible={this.props.visible}>
+ <Text style={styles.navigationBarTitle.label}>{this.props.children}</Text>
+ </PrivateBarItemAnimationContainer>
+ </View>
+ );
+ }
+}
+
+type PrivateBarItemAnimationContainerProps = {
+ visible: boolean,
+ children?: React.Node,
+};
+
+class PrivateBarItemAnimationContainer extends Component<PrivateBarItemAnimationContainerProps> {
+ _opacityValue: Animated.Value;
+ _opacityStyle: Styles.AnimatedViewStyle;
+ _animation: ?Animated.Animation;
+
+ constructor(props: PrivateBarItemAnimationContainerProps) {
+ super(props);
+
+ this._opacityValue = Animated.createValue(props.visible ? 1 : 0);
+ this._opacityStyle = Styles.createAnimatedViewStyle({
+ opacity: this._opacityValue,
+ });
+ }
+
+ shouldComponentUpdate(nextProps: PrivateBarItemAnimationContainerProps) {
+ return this.props.visible !== nextProps.visible || this.props.children !== nextProps.children;
+ }
+
+ componentDidUpdate() {
+ this._animateOpacity(this.props.visible);
+ }
+
+ componentWillUnmount() {
+ if (this._animation) {
+ this._animation.stop();
+ }
+ }
+
+ render() {
+ return <Animated.View style={this._opacityStyle}>{this.props.children}</Animated.View>;
+ }
+
+ _animateOpacity(visible: boolean) {
+ const oldAnimation = this._animation;
+ if (oldAnimation) {
+ oldAnimation.stop();
+ }
+
+ const animation = Animated.timing(this._opacityValue, {
+ toValue: visible ? 1 : 0,
+ easing: Animated.Easing.InOut(),
+ duration: 250,
+ });
+
+ animation.start();
+
+ this._animation = animation;
+ }
+}
+
+/* $FlowFixMe: React.forwardRef is not supported yet by Flow.
+ See: https://github.com/facebook/flow/issues/6103 */
+export const NavigationBar = React.forwardRef(function NavigationBar(props, ref) {
+ return (
+ <NavigationScrollContext.Consumer>
+ {(context) => (
+ <PrivateNavigationBar ref={ref} scrollTop={context.scrollTop}>
+ {props.children}
+ </PrivateNavigationBar>
+ )}
+ </NavigationScrollContext.Consumer>
+ );
+});
+
+type PrivateNavigationBarProps = {
+ scrollTop: number,
+ children?: React.Node,
+};
+
+type PrivateNavigationBarState = {
+ titleAdjustment: number,
+ showsBarSeparator: boolean,
+ showsBarTitle: boolean,
+};
+
+const PrivateTitleBarItemContext = React.createContext({
+ titleAdjustment: 0,
+ visible: false,
+ titleRef: React.createRef(),
+});
+
+class PrivateNavigationBar extends Component<PrivateNavigationBarProps, PrivateNavigationBarState> {
+ static defaultProps = {
+ scrollTop: 0,
+ };
+
+ state = {
+ titleAdjustment: 0,
+ showsBarSeparator: false,
+ showsBarTitle: false,
+ };
+
+ _titleViewRef = React.createRef();
+
+ static getDerivedStateFromProps(props, state) {
+ // that's where SettingsHeader.HeaderTitle intersects the navigation bar
+ const showsBarSeparator = props.scrollTop > 11;
+
+ // that's when SettingsHeader.HeaderTitle goes behind the navigation bar
+ const showsBarTitle = props.scrollTop > 30;
+
+ return {
+ ...state,
+ showsBarSeparator,
+ showsBarTitle,
+ };
+ }
+
+ shouldComponentUpdate(
+ nextProps: PrivateNavigationBarProps,
+ nextState: PrivateNavigationBarState,
+ ) {
+ return (
+ this.props.children !== nextProps.children ||
+ this.state.titleAdjustment !== nextState.titleAdjustment ||
+ this.state.showsBarSeparator !== nextState.showsBarSeparator ||
+ this.state.showsBarTitle !== nextState.showsBarTitle
+ );
+ }
+
+ render() {
+ return (
+ <View
+ style={[
+ styles.navigationBar.default,
+ this.state.showsBarSeparator && styles.navigationBar.separator,
+ styles.navigationBar[process.platform],
+ ]}
+ onLayout={this._onLayout}>
+ <PrivateTitleBarItemContext.Provider
+ value={{
+ titleAdjustment: this.state.titleAdjustment,
+ visible: this.state.showsBarTitle,
+ titleRef: this._titleViewRef,
+ }}>
+ {this.props.children}
+ </PrivateTitleBarItemContext.Provider>
</View>
);
}
+
+ _onLayout = async (containerLayout) => {
+ const titleView = this._titleViewRef.current;
+ if (titleView) {
+ // calculate the title layout frame
+ const titleLayout = await UserInterface.measureLayoutRelativeToAncestor(
+ this._titleViewRef.current,
+ this,
+ );
+
+ // calculate the remaining space at the right hand side
+ const trailingSpace = containerLayout.width - (titleLayout.x + titleLayout.width);
+
+ this.setState({
+ titleAdjustment: titleLayout.x - trailingSpace,
+ });
+ }
+ };
}
+/* $FlowFixMe: React.forwardRef is not supported yet by Flow.
+ See: https://github.com/facebook/flow/issues/6103 */
+export const TitleBarItem = React.forwardRef(function TitleBarItem(props, ref) {
+ return (
+ <PrivateTitleBarItemContext.Consumer>
+ {(context) => (
+ <PrivateTitleBarItem
+ titleAdjustment={context.titleAdjustment}
+ visible={context.visible}
+ ref={(value) => {
+ context.titleRef.current = value;
+
+ if (ref) {
+ if (typeof ref === 'function') {
+ ref(value);
+ } else if (typeof ref === 'object') {
+ ref.current = value;
+ }
+ }
+ }}>
+ {props.children}
+ </PrivateTitleBarItem>
+ )}
+ </PrivateTitleBarItemContext.Consumer>
+ );
+});
+
export class CloseBarItem extends Component {
props: {
action: () => void,
diff --git a/gui/packages/desktop/src/renderer/components/Preferences.js b/gui/packages/desktop/src/renderer/components/Preferences.js
index d0681f7e5e..54e32ccb60 100644
--- a/gui/packages/desktop/src/renderer/components/Preferences.js
+++ b/gui/packages/desktop/src/renderer/components/Preferences.js
@@ -4,7 +4,7 @@ import * as React from 'react';
import { Component, View } from 'reactxp';
import * as Cell from './Cell';
import { Layout, Container } from './Layout';
-import NavigationBar, { BackBarItem } from './NavigationBar';
+import { NavigationBar, BackBarItem } from './NavigationBar';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
import Switch from './Switch';
import styles from './PreferencesStyles';
diff --git a/gui/packages/desktop/src/renderer/components/SelectLocation.js b/gui/packages/desktop/src/renderer/components/SelectLocation.js
index ba599c6e09..d0e91a328b 100644
--- a/gui/packages/desktop/src/renderer/components/SelectLocation.js
+++ b/gui/packages/desktop/src/renderer/components/SelectLocation.js
@@ -5,8 +5,13 @@ import ReactDOM from 'react-dom';
import { View, Component } from 'reactxp';
import { Accordion } from '@mullvad/components';
import { Layout, Container } from './Layout';
-import CustomScrollbars from './CustomScrollbars';
-import NavigationBar, { CloseBarItem } from './NavigationBar';
+import {
+ NavigationContainer,
+ NavigationScrollbars,
+ NavigationBar,
+ CloseBarItem,
+ TitleBarItem,
+} from './NavigationBar';
import SettingsHeader, { HeaderTitle, HeaderSubTitle } from './SettingsHeader';
import * as Cell from './Cell';
import styles from './SelectLocationStyles';
@@ -83,29 +88,29 @@ export default class SelectLocation extends Component<Props, State> {
<Layout>
<Container>
<View style={styles.select_location}>
- <NavigationBar>
- <CloseBarItem action={this.props.onClose} />
- </NavigationBar>
- <View style={styles.container}>
- <SettingsHeader style={styles.title_header}>
- <HeaderTitle>Select location</HeaderTitle>
- </SettingsHeader>
+ <NavigationContainer>
+ <NavigationBar>
+ <CloseBarItem action={this.props.onClose} />
+ <TitleBarItem>{'Select location'}</TitleBarItem>
+ </NavigationBar>
+ <View style={styles.container}>
+ <NavigationScrollbars ref={this._scrollViewRef}>
+ <View style={styles.content}>
+ <SettingsHeader style={styles.subtitle_header}>
+ <HeaderTitle>Select location</HeaderTitle>
+ <HeaderSubTitle>
+ While connected, your real location is masked with a private and secure
+ location in the selected region
+ </HeaderSubTitle>
+ </SettingsHeader>
- <CustomScrollbars ref={this._scrollViewRef}>
- <View style={styles.content}>
- <SettingsHeader style={styles.subtitle_header}>
- <HeaderSubTitle>
- While connected, your real location is masked with a private and secure
- location in the selected region
- </HeaderSubTitle>
- </SettingsHeader>
-
- {this.props.relayLocations.map((relayCountry) => {
- return this._renderCountry(relayCountry);
- })}
- </View>
- </CustomScrollbars>
- </View>
+ {this.props.relayLocations.map((relayCountry) => {
+ return this._renderCountry(relayCountry);
+ })}
+ </View>
+ </NavigationScrollbars>
+ </View>
+ </NavigationContainer>
</View>
</Container>
</Layout>
diff --git a/gui/packages/desktop/src/renderer/components/Settings.js b/gui/packages/desktop/src/renderer/components/Settings.js
index 8edeb25192..82f5dacd6d 100644
--- a/gui/packages/desktop/src/renderer/components/Settings.js
+++ b/gui/packages/desktop/src/renderer/components/Settings.js
@@ -7,9 +7,14 @@ import * as AppButton from './AppButton';
import * as Cell from './Cell';
import Img from './Img';
import { Layout, Container } from './Layout';
-import NavigationBar, { CloseBarItem } from './NavigationBar';
+import {
+ NavigationBar,
+ NavigationContainer,
+ NavigationScrollbars,
+ CloseBarItem,
+ TitleBarItem,
+} from './NavigationBar';
import SettingsHeader, { HeaderTitle } from './SettingsHeader';
-import CustomScrollbars from './CustomScrollbars';
import styles from './SettingsStyles';
import { colors } from '../../config';
@@ -36,26 +41,28 @@ export default class Settings extends Component<Props> {
<Layout>
<Container>
<View style={styles.settings}>
- <NavigationBar>
- <CloseBarItem action={this.props.onClose} />
- </NavigationBar>
+ <NavigationContainer>
+ <NavigationBar>
+ <CloseBarItem action={this.props.onClose} />
+ <TitleBarItem>Settings</TitleBarItem>
+ </NavigationBar>
- <View style={styles.settings__container}>
- <SettingsHeader>
- <HeaderTitle>Settings</HeaderTitle>
- </SettingsHeader>
-
- <CustomScrollbars style={styles.settings__scrollview}>
- <View style={styles.settings__content}>
- <View>
- {this._renderTopButtons()}
- {this._renderMiddleButtons()}
- {this._renderBottomButtons()}
+ <View style={styles.settings__container}>
+ <NavigationScrollbars style={styles.settings__scrollview}>
+ <View style={styles.settings__content}>
+ <SettingsHeader>
+ <HeaderTitle>Settings</HeaderTitle>
+ </SettingsHeader>
+ <View>
+ {this._renderTopButtons()}
+ {this._renderMiddleButtons()}
+ {this._renderBottomButtons()}
+ </View>
+ {this._renderQuitButton()}
</View>
- {this._renderQuitButton()}
- </View>
- </CustomScrollbars>
- </View>
+ </NavigationScrollbars>
+ </View>
+ </NavigationContainer>
</View>
</Container>
</Layout>
@@ -158,24 +165,17 @@ export default class Settings extends Component<Props> {
_renderBottomButtons() {
return (
<View>
- <Cell.CellButton
- onPress={this.props.onExternalLink.bind(this, 'faq')}
- testName="settings__external_link">
- <Cell.Label>FAQs</Cell.Label>
- <Cell.Icon height={16} width={16} source="icon-extLink" />
+ <Cell.CellButton onPress={this.props.onViewSupport} testName="settings__view_support">
+ <Cell.Label>Report a problem</Cell.Label>
+ <Cell.Icon height={12} width={7} source="icon-chevron" />
</Cell.CellButton>
<Cell.CellButton
- onPress={this.props.onExternalLink.bind(this, 'guides')}
+ onPress={this.props.onExternalLink.bind(this, 'faq')}
testName="settings__external_link">
- <Cell.Label>Guides</Cell.Label>
+ <Cell.Label>{'FAQs & Guides'}</Cell.Label>
<Cell.Icon height={16} width={16} source="icon-extLink" />
</Cell.CellButton>
-
- <Cell.CellButton onPress={this.props.onViewSupport} testName="settings__view_support">
- <Cell.Label>Report a problem</Cell.Label>
- <Cell.Icon height={12} width={7} source="icon-chevron" />
- </Cell.CellButton>
</View>
);
}
diff --git a/gui/packages/desktop/src/renderer/components/SettingsHeader.js b/gui/packages/desktop/src/renderer/components/SettingsHeader.js
index fdd982922f..1e5412b03d 100644
--- a/gui/packages/desktop/src/renderer/components/SettingsHeader.js
+++ b/gui/packages/desktop/src/renderer/components/SettingsHeader.js
@@ -10,7 +10,7 @@ const styles = {
flexGrow: 0,
flexShrink: 0,
flexBasis: 'auto',
- paddingTop: 16,
+ paddingTop: 4,
paddingRight: 24,
paddingLeft: 24,
paddingBottom: 24,
diff --git a/gui/packages/desktop/src/renderer/components/Support.js b/gui/packages/desktop/src/renderer/components/Support.js
index 2552a0e432..8cbc584be7 100644
--- a/gui/packages/desktop/src/renderer/components/Support.js
+++ b/gui/packages/desktop/src/renderer/components/Support.js
@@ -4,7 +4,7 @@ import * as React from 'react';
import { Component, Text, View, TextInput } from 'reactxp';
import * as AppButton from './AppButton';
import { Layout, Container } from './Layout';
-import NavigationBar, { BackBarItem } from './NavigationBar';
+import { NavigationBar, BackBarItem } from './NavigationBar';
import SettingsHeader, { HeaderTitle, HeaderSubTitle } from './SettingsHeader';
import styles from './SupportStyles';
import Img from './Img';
@@ -290,7 +290,7 @@ export default class Support extends Component<SupportProps, SupportState> {
<Text style={styles.support__sent_message}>Thanks! We will look into this.</Text>
{this.state.email.trim().length > 0 ? (
<Text style={styles.support__sent_message}>
- If needed we will contact you on {'\u00A0'}
+ {'If needed we will contact you on '}
<Text style={styles.support__sent_email}>{this.state.email}</Text>
</Text>
) : null}
diff --git a/gui/packages/desktop/test/components/Settings.spec.js b/gui/packages/desktop/test/components/Settings.spec.js
index 251bd15855..aa9709e2de 100644
--- a/gui/packages/desktop/test/components/Settings.spec.js
+++ b/gui/packages/desktop/test/components/Settings.spec.js
@@ -204,7 +204,7 @@ describe('components/Settings', () => {
.find({ testName: 'settings__external_link' })
.forEach((element) => element.simulate('press'));
- expect(collectedExternalLinkTypes).to.include.ordered.members(['faq', 'guides']);
+ expect(collectedExternalLinkTypes).to.include.ordered.members(['faq']);
});
});
diff --git a/gui/yarn.lock b/gui/yarn.lock
index 053c0e1753..cb1b4365c3 100644
--- a/gui/yarn.lock
+++ b/gui/yarn.lock
@@ -3580,24 +3580,24 @@ escodegen@^1.9.1:
optionalDependencies:
source-map "~0.6.1"
-eslint-config-prettier@^2.9.0:
- version "2.10.0"
- resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.10.0.tgz#ec07bc1d01f87d09f61d3840d112dc8a9791e30b"
- integrity sha512-Mhl90VLucfBuhmcWBgbUNtgBiK955iCDK1+aHAz7QfDQF6wuzWZ6JjihZ3ejJoGlJWIuko7xLqNm8BA5uenKhA==
+eslint-config-prettier@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz#2c26d2cdcfa3a05f0642cd7e6e4ef3316cdabfa2"
+ integrity sha512-QYGfmzuc4q4J6XIhlp8vRKdI/fI0tQfQPy1dME3UOLprE+v4ssH/3W9LM2Q7h5qBcy5m0ehCrBDU2YF8q6OY8w==
dependencies:
- get-stdin "^5.0.1"
+ get-stdin "^6.0.0"
-eslint-plugin-flowtype@^2.50.0:
- version "2.50.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.0.tgz#953e262fa9b5d0fa76e178604892cf60dfb916da"
- integrity sha512-10FnBXCp8odYcpUFXGAh+Zko7py0hUWutTd3BN/R9riukH360qNPLYPR3/xV9eu9K7OJDjJrsflBnL6RwxFnlw==
+eslint-plugin-flowtype@^2.50.3:
+ version "2.50.3"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.50.3.tgz#61379d6dce1d010370acd6681740fd913d68175f"
+ integrity sha512-X+AoKVOr7Re0ko/yEXyM5SSZ0tazc6ffdIOocp2fFUlWoDt7DV0Bz99mngOkAFLOAWjqRA5jPwqUCbrx13XoxQ==
dependencies:
lodash "^4.17.10"
-eslint-plugin-promise@^3.8.0:
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621"
- integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==
+eslint-plugin-promise@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz#2d074b653f35a23d1ba89d8e976a985117d1c6a2"
+ integrity sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==
eslint-plugin-react@^7.10.0:
version "7.11.1"
@@ -4059,10 +4059,10 @@ flat-cache@^1.2.1:
graceful-fs "^4.1.2"
write "^0.2.1"
-flow-bin@0.78:
- version "0.78.0"
- resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.78.0.tgz#df9fe7f9c9a2dfaff39083949fe2d831b41627b7"
- integrity sha512-LV55tE+ItkC9HQAbEK+VxpBe54Ryp/dj4q9KmqDIfhV7mtP+hbvc/1AUf/AaWFIve3eURO0cxoGN4ZQQ3o2HTg==
+flow-bin@0.82:
+ version "0.82.0"
+ resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.82.0.tgz#fbec84c0d6cab7877565eca8214d655f3aefb8db"
+ integrity sha512-D7ViTCVJSVv19CB6dFWS9k2iKQlavtkRXn9el0ofVTTpGuybe+EPE8DZwdyohzEt6wRhHV8gwkteWvxdcVuOzg==
flow-typed@^2.5.1:
version "2.5.1"
@@ -4282,10 +4282,10 @@ get-stdin@^4.0.1:
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
-get-stdin@^5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
- integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=
+get-stdin@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
+ integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==
get-stream@^3.0.0:
version "3.0.0"
@@ -6862,10 +6862,10 @@ preserve@^0.2.0:
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
-prettier@1.13.7:
- version "1.13.7"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281"
- integrity sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==
+prettier@1.14.3:
+ version "1.14.3"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895"
+ integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==
prettier@^1.13.7:
version "1.14.2"