diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-09-17 10:18:52 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-09-17 10:18:52 +0200 |
| commit | e3596cc4f8e8b3d37e780ec7c23b3cffe375fc7b (patch) | |
| tree | 11fa5bd3920270ec0f390baaf900b409700f00d6 | |
| parent | 34d71197d52d8050a05d4cc715568409a06c888c (diff) | |
| parent | e901869aee45d171e189bb0cae3af478cb325a4c (diff) | |
| download | mullvadvpn-e3596cc4f8e8b3d37e780ec7c23b3cffe375fc7b.tar.xz mullvadvpn-e3596cc4f8e8b3d37e780ec7c23b3cffe375fc7b.zip | |
Merge branch 'select-location-ux'
| -rw-r--r-- | gui/src/renderer/components/Account.tsx | 12 | ||||
| -rw-r--r-- | gui/src/renderer/components/AdvancedSettings.tsx | 19 | ||||
| -rw-r--r-- | gui/src/renderer/components/CustomScrollbars.tsx | 9 | ||||
| -rw-r--r-- | gui/src/renderer/components/NavigationBar.tsx | 178 | ||||
| -rw-r--r-- | gui/src/renderer/components/Preferences.tsx | 19 | ||||
| -rw-r--r-- | gui/src/renderer/components/SelectLocation.tsx | 125 | ||||
| -rw-r--r-- | gui/src/renderer/components/SelectLocationStyles.tsx | 16 | ||||
| -rw-r--r-- | gui/src/renderer/components/Settings.tsx | 13 | ||||
| -rw-r--r-- | gui/src/renderer/components/SettingsHeader.tsx | 33 | ||||
| -rw-r--r-- | gui/src/renderer/components/Support.tsx | 12 | ||||
| -rw-r--r-- | gui/src/renderer/components/WireguardKeys.tsx | 12 |
11 files changed, 184 insertions, 264 deletions
diff --git a/gui/src/renderer/components/Account.tsx b/gui/src/renderer/components/Account.tsx index efe8ff2d13..fb4eb6bf35 100644 --- a/gui/src/renderer/components/Account.tsx +++ b/gui/src/renderer/components/Account.tsx @@ -6,7 +6,7 @@ import styles from './AccountStyles'; import * as AppButton from './AppButton'; import ClipboardLabel from './ClipboardLabel'; import { Container, Layout } from './Layout'; -import { BackBarItem, NavigationBar } from './NavigationBar'; +import { BackBarItem, NavigationBar, NavigationItems } from './NavigationBar'; import SettingsHeader, { HeaderTitle } from './SettingsHeader'; import { AccountToken } from '../../shared/daemon-rpc-types'; @@ -28,10 +28,12 @@ export default class Account extends Component<IProps> { <Container> <View style={styles.account}> <NavigationBar> - <BackBarItem action={this.props.onClose}> - {// TRANSLATORS: Back button in navigation bar - messages.pgettext('account-nav', 'Settings')} - </BackBarItem> + <NavigationItems> + <BackBarItem action={this.props.onClose}> + {// TRANSLATORS: Back button in navigation bar + messages.pgettext('account-nav', 'Settings')} + </BackBarItem> + </NavigationItems> </NavigationBar> <View style={styles.account__container}> diff --git a/gui/src/renderer/components/AdvancedSettings.tsx b/gui/src/renderer/components/AdvancedSettings.tsx index 6abf4c4958..c9a985789b 100644 --- a/gui/src/renderer/components/AdvancedSettings.tsx +++ b/gui/src/renderer/components/AdvancedSettings.tsx @@ -11,6 +11,7 @@ import { BackBarItem, NavigationBar, NavigationContainer, + NavigationItems, NavigationScrollbars, TitleBarItem, } from './NavigationBar'; @@ -162,14 +163,16 @@ export default class AdvancedSettings extends Component<IProps, IState> { <View style={styles.advanced_settings}> <NavigationContainer> <NavigationBar> - <BackBarItem action={this.props.onClose}> - {// TRANSLATORS: Back button in navigation bar - messages.pgettext('advanced-settings-nav', 'Settings')} - </BackBarItem> - <TitleBarItem> - {// TRANSLATORS: Title label in navigation bar - messages.pgettext('advanced-settings-nav', 'Advanced')} - </TitleBarItem> + <NavigationItems> + <BackBarItem action={this.props.onClose}> + {// TRANSLATORS: Back button in navigation bar + messages.pgettext('advanced-settings-nav', 'Settings')} + </BackBarItem> + <TitleBarItem> + {// TRANSLATORS: Title label in navigation bar + messages.pgettext('advanced-settings-nav', 'Advanced')} + </TitleBarItem> + </NavigationItems> </NavigationBar> <View style={styles.advanced_settings__container}> diff --git a/gui/src/renderer/components/CustomScrollbars.tsx b/gui/src/renderer/components/CustomScrollbars.tsx index 8928e9891b..fc91d7d239 100644 --- a/gui/src/renderer/components/CustomScrollbars.tsx +++ b/gui/src/renderer/components/CustomScrollbars.tsx @@ -86,6 +86,15 @@ export default class CustomScrollbars extends React.Component<IProps, IState> { } } + public getScrollPosition(): [number, number] { + const scroll = this.scrollableRef.current; + if (scroll) { + return [scroll.scrollLeft, scroll.scrollTop]; + } else { + return [0, 0]; + } + } + public componentDidMount() { this.updateScrollbarsHelper({ position: true, diff --git a/gui/src/renderer/components/NavigationBar.tsx b/gui/src/renderer/components/NavigationBar.tsx index dd36c08850..cba9df0786 100644 --- a/gui/src/renderer/components/NavigationBar.tsx +++ b/gui/src/renderer/components/NavigationBar.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import * as ReactDOM from 'react-dom'; import { Animated, Button, Component, Styles, Text, Types, UserInterface, View } from 'reactxp'; import { colors } from '../../config.json'; import CustomScrollbars, { IScrollEvent } from './CustomScrollbars'; @@ -12,9 +11,9 @@ const styles = { paddingHorizontal: 12, paddingBottom: 12, }), - content: Styles.createViewStyle({ + wrapper: Styles.createViewStyle({ flex: 1, - flexDirection: 'row', + flexDirection: 'column', }), separator: Styles.createViewStyle({ backgroundColor: 'rgba(0, 0, 0, 0.2)', @@ -34,6 +33,10 @@ const styles = { paddingTop: 12, }), }, + navigationItems: Styles.createViewStyle({ + flex: 1, + flexDirection: 'row', + }), navigationBarTitle: { container: Styles.createViewStyle({ flex: 1, @@ -100,7 +103,7 @@ const styles = { paddingVertical: 4, }), selected: Styles.createButtonStyle({ - backgroundColor: colors.blue, + backgroundColor: colors.green, }), hover: Styles.createButtonStyle({ backgroundColor: colors.blue40, @@ -113,13 +116,6 @@ const styles = { }), }, }, - stickyContentHolder: Styles.createViewStyle({ - position: 'absolute', - top: 0, - left: 0, - right: 0, - backgroundColor: colors.darkBlue, - }), }; interface INavigationScrollContextValue { @@ -178,15 +174,8 @@ export class NavigationContainer extends Component { } private updateBarAppearance(event: IScrollEvent) { - // detect if any of child elements provide a sticky context - // in that case the navigation bar does not draw the separator line - // since the sticky content is expected to include it. - const hasSticky = React.Children.toArray(this.props.children).some((child) => { - return React.isValidElement(child) && child.type === StickyContentContainer; - }); - // that's where SettingsHeader.HeaderTitle intersects the navigation bar - const showsBarSeparator = event.scrollTop > 11 && !hasSticky; + const showsBarSeparator = event.scrollTop > 11; // that's when SettingsHeader.HeaderTitle goes behind the navigation bar const showsBarTitle = event.scrollTop > 20; @@ -344,87 +333,6 @@ class PrivateBarItemAnimationContainer extends Component<IPrivateBarItemAnimatio } } -interface IStickyContentContext { - container: HTMLDivElement | null; - holder: React.Ref<View>; - isSticky: boolean; -} - -const StickyContentContext = React.createContext<IStickyContentContext>({ - container: null, - holder: React.createRef<View>(), - isSticky: false, -}); - -export class StickyContentContainer extends Component<{ - style: Types.StyleRuleSet<Types.ViewStyle>; -}> { - public static contextType = NavigationScrollContext; - public context!: React.ContextType<typeof NavigationScrollContext>; - - public state = { - container: null, - holder: React.createRef<View>(), - isSticky: false, - }; - - public componentDidMount() { - if (this.context.navigationContainer) { - this.context.navigationContainer.addScrollEventListener(this.onScroll); - } - } - - public componentWillUnmount() { - if (this.context.navigationContainer) { - this.context.navigationContainer.removeScrollEventListener(this.onScroll); - } - } - - public render() { - return ( - <div - ref={this.onRef} - style={{ - position: 'relative', - display: 'flex', - flexDirection: 'column', - overflow: 'hidden', - }}> - <View style={this.props.style}> - <StickyContentContext.Provider value={this.state}> - {this.props.children} - </StickyContentContext.Provider> - </View> - </div> - ); - } - - private onScroll = async (_scrollEvent: IScrollEvent) => { - const holder = this.state.holder.current; - - if (holder) { - let layout: Types.LayoutInfo; - - try { - layout = await UserInterface.measureLayoutRelativeToAncestor(holder, this); - } catch { - // TODO: handle error - return; - } - - const isSticky = layout.y <= 0; - - if (this.state.isSticky !== isSticky) { - this.setState({ isSticky }); - } - } - }; - - private onRef = (ref: HTMLDivElement | null) => { - this.setState({ container: ref }); - }; -} - interface IScopeBarProps { defaultSelectedIndex: number; onChange?: (selectedIndex: number) => void; @@ -493,67 +401,6 @@ export class ScopeBar extends Component<IScopeBarProps, IScopeBarState> { } } -interface IStickyContentHolderProps { - style?: Types.ViewStyleRuleSet; -} - -interface IStickyContentHolderState { - contentHeight: number; -} - -export class StickyContentHolder extends Component< - IStickyContentHolderProps, - IStickyContentHolderState -> { - public state = { - contentHeight: 0, - }; - - public render() { - return ( - <StickyContentContext.Consumer> - {(stickyContext) => { - const contentStyle = stickyContext.isSticky ? styles.stickyContentHolder : undefined; - const contentPlaceholderStyle = stickyContext.isSticky - ? Styles.createViewStyle( - { - height: this.state.contentHeight, - }, - false, - ) - : undefined; - - const children = ( - <View style={contentStyle} onLayout={this.onLayout}> - {this.props.children} - {stickyContext.isSticky ? <NavigationBarSeparator /> : undefined} - </View> - ); - - return ( - <View style={this.props.style} ref={stickyContext.holder}> - {stickyContext.isSticky && stickyContext.container ? ( - <React.Fragment> - <View style={contentPlaceholderStyle} /> - {ReactDOM.createPortal(children, stickyContext.container)} - </React.Fragment> - ) : ( - children - )} - </View> - ); - }} - </StickyContentContext.Consumer> - ); - } - - private onLayout = async (layout: Types.LayoutInfo) => { - if (this.state.contentHeight !== layout.height) { - this.setState({ contentHeight: layout.height }); - } - }; -} - interface IScopeBarItemProps { children?: React.ReactText; selected?: boolean; @@ -598,6 +445,7 @@ function NavigationBarSeparator() { interface INavigationBarProps { children?: React.ReactNode; + alwaysDisplayBarTitle?: boolean; } export const NavigationBar = React.forwardRef(function NavigationBarT( @@ -609,7 +457,7 @@ export const NavigationBar = React.forwardRef(function NavigationBarT( {(context) => ( <PrivateNavigationBar ref={ref} - showsBarTitle={context.showsBarTitle} + showsBarTitle={props.alwaysDisplayBarTitle || context.showsBarTitle} showsBarSeparator={context.showsBarSeparator}> {props.children} </PrivateNavigationBar> @@ -635,6 +483,10 @@ const PrivateTitleBarItemContext = React.createContext({ measuringTextRef: React.createRef<Text>(), }); +export function NavigationItems(props: { children: React.ReactNode }) { + return <View style={styles.navigationItems}>{props.children}</View>; +} + class PrivateNavigationBar extends Component< IPrivateNavigationBarProps, IPrivateNavigationBarState @@ -661,7 +513,7 @@ class PrivateNavigationBar extends Component< public render() { return ( <View style={[styles.navigationBar.default, this.getPlatformStyle()]}> - <View style={styles.navigationBar.content} onLayout={this.onLayout}> + <View style={styles.navigationBar.wrapper} onLayout={this.onLayout}> <PrivateTitleBarItemContext.Provider value={{ titleAdjustment: this.state.titleAdjustment, diff --git a/gui/src/renderer/components/Preferences.tsx b/gui/src/renderer/components/Preferences.tsx index 2c6df58a99..b295c68308 100644 --- a/gui/src/renderer/components/Preferences.tsx +++ b/gui/src/renderer/components/Preferences.tsx @@ -7,6 +7,7 @@ import { BackBarItem, NavigationBar, NavigationContainer, + NavigationItems, NavigationScrollbars, TitleBarItem, } from './NavigationBar'; @@ -39,14 +40,16 @@ export default class Preferences extends Component<IProps> { <View style={styles.preferences}> <NavigationContainer> <NavigationBar> - <BackBarItem action={this.props.onClose}> - {// TRANSLATORS: Back button in navigation bar - messages.pgettext('preferences-nav', 'Settings')} - </BackBarItem> - <TitleBarItem> - {// TRANSLATORS: Title label in navigation bar - messages.pgettext('preferences-nav', 'Preferences')} - </TitleBarItem> + <NavigationItems> + <BackBarItem action={this.props.onClose}> + {// TRANSLATORS: Back button in navigation bar + messages.pgettext('preferences-nav', 'Settings')} + </BackBarItem> + <TitleBarItem> + {// TRANSLATORS: Title label in navigation bar + messages.pgettext('preferences-nav', 'Preferences')} + </TitleBarItem> + </NavigationItems> </NavigationBar> <View style={styles.preferences__container}> diff --git a/gui/src/renderer/components/SelectLocation.tsx b/gui/src/renderer/components/SelectLocation.tsx index 7a1340c44f..0018446291 100644 --- a/gui/src/renderer/components/SelectLocation.tsx +++ b/gui/src/renderer/components/SelectLocation.tsx @@ -14,15 +14,14 @@ import { CloseBarItem, NavigationBar, NavigationContainer, + NavigationItems, NavigationScrollbars, ScopeBar, ScopeBarItem, - StickyContentContainer, - StickyContentHolder, TitleBarItem, } from './NavigationBar'; import styles from './SelectLocationStyles'; -import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader'; +import { HeaderSubTitle } from './SettingsHeader'; interface IProps { locationScope: LocationScope; @@ -43,13 +42,29 @@ export default class SelectLocation extends Component<IProps> { private exitLocationList = React.createRef<LocationList>(); private bridgeLocationList = React.createRef<LocationList>(); + private scrollPositionByScope: { [index: number]: [number, number] } = {}; + public componentDidMount() { this.scrollToSelectedCell(); } - public componentDidUpdate(prevProps: IProps) { + public componentDidUpdate(prevProps: IProps, _prevState: {}, snapshot?: [number, number]) { if (this.props.locationScope !== prevProps.locationScope) { - this.scrollToSelectedCell(); + this.restoreScrollPosition(this.props.locationScope); + + if (snapshot) { + this.saveScrollPosition(prevProps.locationScope, snapshot); + } + } + } + + public getSnapshotBeforeUpdate(_prevProps: IProps) { + const scrollView = this.scrollView.current; + + if (scrollView) { + return scrollView.getScrollPosition(); + } else { + return undefined; } } @@ -59,51 +74,44 @@ export default class SelectLocation extends Component<IProps> { <Container> <View style={styles.select_location}> <NavigationContainer> - <NavigationBar> - <CloseBarItem action={this.props.onClose} /> - <TitleBarItem> - {// TRANSLATORS: Title label in navigation bar - messages.pgettext('select-location-nav', 'Select location')} - </TitleBarItem> + <NavigationBar alwaysDisplayBarTitle={true}> + <NavigationItems> + <CloseBarItem action={this.props.onClose} /> + <TitleBarItem> + {// TRANSLATORS: Title label in navigation bar + messages.pgettext('select-location-nav', 'Select location')} + </TitleBarItem> + </NavigationItems> + <View style={styles.navigationBarAttachment}> + <HeaderSubTitle> + {this.props.allowBridgeSelection + ? messages.pgettext( + 'select-location-view', + 'While connected, your traffic will be routed through two secure locations, the entry point (a bridge server) and the exit point (a VPN server).', + ) + : messages.pgettext( + 'select-location-view', + 'While connected, your real location is masked with a private and secure location in the selected region.', + )} + </HeaderSubTitle> + {this.props.allowBridgeSelection && ( + <ScopeBar + style={styles.scopeBar} + defaultSelectedIndex={this.props.locationScope} + onChange={this.props.onChangeLocationScope}> + <ScopeBarItem> + {messages.pgettext('select-location-nav', 'Entry')} + </ScopeBarItem> + <ScopeBarItem> + {messages.pgettext('select-location-nav', 'Exit')} + </ScopeBarItem> + </ScopeBar> + )} + </View> </NavigationBar> - <StickyContentContainer style={styles.container}> + <View style={styles.container}> <NavigationScrollbars ref={this.scrollView}> <View style={styles.content}> - <SettingsHeader - style={this.props.allowBridgeSelection ? styles.headerWithScope : undefined}> - <HeaderTitle> - {messages.pgettext('select-location-view', 'Select location')} - </HeaderTitle> - <HeaderSubTitle> - {this.props.locationScope === LocationScope.relay - ? messages.pgettext( - 'select-location-view', - 'While connected, your real location is masked with a private and secure location in the selected region', - ) - : messages.pgettext( - 'select-location-view', - 'While connected, your traffic will be routed through two secure locations, the entry point (a bridge server) and the exit point (a VPN server)', - )} - </HeaderSubTitle> - </SettingsHeader> - - {this.props.allowBridgeSelection && ( - <StickyContentHolder style={styles.stickyHolder}> - <View style={styles.stickyContent}> - <ScopeBar - defaultSelectedIndex={this.props.locationScope} - onChange={this.props.onChangeLocationScope}> - <ScopeBarItem> - {messages.pgettext('select-location-nav', 'Entry')} - </ScopeBarItem> - <ScopeBarItem> - {messages.pgettext('select-location-nav', 'Exit')} - </ScopeBarItem> - </ScopeBar> - </View> - </StickyContentHolder> - )} - {this.props.locationScope === LocationScope.relay ? ( <LocationList key={'exit-locations'} @@ -135,7 +143,7 @@ export default class SelectLocation extends Component<IProps> { )} </View> </NavigationScrollbars> - </StickyContentContainer> + </View> </NavigationContainer> </View> </Container> @@ -143,6 +151,27 @@ export default class SelectLocation extends Component<IProps> { ); } + public saveScrollPosition(scope: LocationScope, position: [number, number]) { + this.scrollPositionByScope[scope] = position; + } + + public restoreScrollPosition(scope: LocationScope) { + const prevScrollPos = this.scrollPositionByScope[scope]; + + if (prevScrollPos) { + this.scrollToPosition(...prevScrollPos); + } else { + this.scrollToSelectedCell(); + } + } + + private scrollToPosition(x: number, y: number) { + const scrollView = this.scrollView.current; + if (scrollView) { + scrollView.scrollTo(x, y); + } + } + private scrollToSelectedCell() { const ref = this.props.locationScope === LocationScope.relay diff --git a/gui/src/renderer/components/SelectLocationStyles.tsx b/gui/src/renderer/components/SelectLocationStyles.tsx index bfda9c1055..ad6c116436 100644 --- a/gui/src/renderer/components/SelectLocationStyles.tsx +++ b/gui/src/renderer/components/SelectLocationStyles.tsx @@ -13,18 +13,12 @@ export default { content: Styles.createViewStyle({ overflow: 'visible', }), - headerWithScope: Styles.createViewStyle({ - paddingBottom: 4, + navigationBarAttachment: Styles.createTextStyle({ + marginTop: 8, + paddingHorizontal: 4, }), - stickyHolder: Styles.createViewStyle({ - marginTop: 4, - }), - stickyContent: Styles.createViewStyle({ - paddingHorizontal: 12, - paddingBottom: 8, - - // NavigationBar already adds some spacing - paddingTop: 0, + scopeBar: Styles.createViewStyle({ + marginTop: 8, }), selectedCell: Styles.createViewStyle({ backgroundColor: colors.green, diff --git a/gui/src/renderer/components/Settings.tsx b/gui/src/renderer/components/Settings.tsx index bf0e812a89..6c04d9a8e5 100644 --- a/gui/src/renderer/components/Settings.tsx +++ b/gui/src/renderer/components/Settings.tsx @@ -11,6 +11,7 @@ import { CloseBarItem, NavigationBar, NavigationContainer, + NavigationItems, NavigationScrollbars, TitleBarItem, } from './NavigationBar'; @@ -44,11 +45,13 @@ export default class Settings extends Component<IProps> { <View style={styles.settings}> <NavigationContainer> <NavigationBar> - <CloseBarItem action={this.props.onClose} /> - <TitleBarItem> - {// TRANSLATORS: Title label in navigation bar - messages.pgettext('settings-view-nav', 'Settings')} - </TitleBarItem> + <NavigationItems> + <CloseBarItem action={this.props.onClose} /> + <TitleBarItem> + {// TRANSLATORS: Title label in navigation bar + messages.pgettext('settings-view-nav', 'Settings')} + </TitleBarItem> + </NavigationItems> </NavigationBar> <View style={styles.settings__container}> diff --git a/gui/src/renderer/components/SettingsHeader.tsx b/gui/src/renderer/components/SettingsHeader.tsx index 57be8653c4..9ddfa171c2 100644 --- a/gui/src/renderer/components/SettingsHeader.tsx +++ b/gui/src/renderer/components/SettingsHeader.tsx @@ -20,7 +20,6 @@ const styles = { color: colors.white, }), subtitle: Styles.createTextStyle({ - marginTop: 8, fontFamily: 'Open Sans', fontSize: 13, fontWeight: '600', @@ -29,26 +28,48 @@ const styles = { lineHeight: 20, letterSpacing: -0.2, }), + spacer: Styles.createViewStyle({ + height: 8, + }), }; interface ISettingsHeaderProps { style?: Types.ViewStyleRuleSet; } +interface ISettingsTextProps { + style?: Types.TextStyleRuleSet; +} + export default class SettingsHeader extends Component<ISettingsHeaderProps> { public render() { - return <View style={[styles.header.default, this.props.style]}>{this.props.children}</View>; + return ( + <View style={[styles.header.default, this.props.style]}> + {React.Children.map(this.props.children, (child, index) => { + if (React.isValidElement(child) && index > 0) { + return ( + <React.Fragment> + <View style={styles.spacer} /> + {child} + </React.Fragment> + ); + } else { + return child; + } + })} + </View> + ); } } -export class HeaderTitle extends Component { +export class HeaderTitle extends Component<ISettingsTextProps> { public render() { - return <Text style={[styles.title]}>{this.props.children}</Text>; + return <Text style={[styles.title, this.props.style]}>{this.props.children}</Text>; } } -export class HeaderSubTitle extends Component { +export class HeaderSubTitle extends Component<ISettingsTextProps> { public render() { - return <Text style={[styles.subtitle]}>{this.props.children}</Text>; + return <Text style={[styles.subtitle, this.props.style]}>{this.props.children}</Text>; } } diff --git a/gui/src/renderer/components/Support.tsx b/gui/src/renderer/components/Support.tsx index c3b7d42993..02f374737d 100644 --- a/gui/src/renderer/components/Support.tsx +++ b/gui/src/renderer/components/Support.tsx @@ -5,7 +5,7 @@ import * as AppButton from './AppButton'; import ImageView from './ImageView'; import { Container, Layout } from './Layout'; import { ModalAlert, ModalContainer, ModalContent } from './Modal'; -import { BackBarItem, NavigationBar } from './NavigationBar'; +import { BackBarItem, NavigationBar, NavigationItems } from './NavigationBar'; import SettingsHeader, { HeaderSubTitle, HeaderTitle } from './SettingsHeader'; import styles from './SupportStyles'; @@ -139,10 +139,12 @@ export default class Support extends Component<ISupportProps, ISupportState> { <ModalContent> <View style={styles.support}> <NavigationBar> - <BackBarItem action={this.props.onClose}> - {// TRANSLATORS: Back button in navigation bar - messages.pgettext('support-nav', 'Settings')} - </BackBarItem> + <NavigationItems> + <BackBarItem action={this.props.onClose}> + {// TRANSLATORS: Back button in navigation bar + messages.pgettext('support-nav', 'Settings')} + </BackBarItem> + </NavigationItems> </NavigationBar> <View style={styles.support__container}> {header} diff --git a/gui/src/renderer/components/WireguardKeys.tsx b/gui/src/renderer/components/WireguardKeys.tsx index 9ea386ec91..053b8567c7 100644 --- a/gui/src/renderer/components/WireguardKeys.tsx +++ b/gui/src/renderer/components/WireguardKeys.tsx @@ -8,7 +8,7 @@ import { IWgKey, WgKeyState } from '../redux/settings/reducers'; import * as AppButton from './AppButton'; import ImageView from './ImageView'; import { Container, Layout } from './Layout'; -import { BackBarItem, NavigationBar, NavigationContainer } from './NavigationBar'; +import { BackBarItem, NavigationBar, NavigationContainer, NavigationItems } from './NavigationBar'; import SettingsHeader, { HeaderTitle } from './SettingsHeader'; import styles from './WireguardKeysStyles'; @@ -32,10 +32,12 @@ export default class WireguardKeys extends Component<IProps> { <View style={styles.wgkeys}> <NavigationContainer> <NavigationBar> - <BackBarItem action={this.props.onClose}> - {// TRANSLATORS: Back button in navigation bar - messages.pgettext('wireguard-keys-nav', 'Advanced')} - </BackBarItem> + <NavigationItems> + <BackBarItem action={this.props.onClose}> + {// TRANSLATORS: Back button in navigation bar + messages.pgettext('wireguard-keys-nav', 'Advanced')} + </BackBarItem> + </NavigationItems> </NavigationBar> </NavigationContainer> |
