diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2018-10-08 14:25:30 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2018-10-08 14:25:30 +0200 |
| commit | af6141a0667665a078d1cb90202accaeaca21fef (patch) | |
| tree | 50a6f77d00cb9f664c003f3d94cc153322b66ff8 | |
| parent | c16b7bb907227c5bd186c03f49829ddb652815b4 (diff) | |
| parent | 127a19c557097cddecbda1f6031957736855548a (diff) | |
| download | mullvadvpn-af6141a0667665a078d1cb90202accaeaca21fef.tar.xz mullvadvpn-af6141a0667665a078d1cb90202accaeaca21fef.zip | |
Merge branch 'smart-navigation-title'
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" |
