From 90acb9e406de53856a634003f4114635d6c8ed07 Mon Sep 17 00:00:00 2001 From: Spencer Carli Date: Fri, 29 Sep 2017 16:11:30 -0500 Subject: [PATCH] Improve StatusBar/Header Behavior (#2669) * Track orientation change * Add tests for withOrientation * Better variable naming --- packages/react-navigation/package.json | 2 +- .../react-navigation/src/TypeDefinition.js | 1 + .../src/views/Header/Header.js | 18 ++++-- .../withOrientation-test.js.snap | 7 +++ .../views/__tests__/withOrientation-test.js | 15 +++++ .../src/views/withOrientation.js | 55 +++++++++++++++++++ packages/react-navigation/yarn.lock | 22 ++++++-- 7 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 packages/react-navigation/src/views/__tests__/__snapshots__/withOrientation-test.js.snap create mode 100644 packages/react-navigation/src/views/__tests__/withOrientation-test.js create mode 100644 packages/react-navigation/src/views/withOrientation.js diff --git a/packages/react-navigation/package.json b/packages/react-navigation/package.json index 42f46153..0bedd2cf 100644 --- a/packages/react-navigation/package.json +++ b/packages/react-navigation/package.json @@ -83,7 +83,7 @@ "react": "16.0.0-alpha.12", "react-native": "^0.48.4", "react-native-vector-icons": "^4.2.0", - "react-test-renderer": "^15.6.1" + "react-test-renderer": "^16.0.0" }, "jest": { "notify": true, diff --git a/packages/react-navigation/src/TypeDefinition.js b/packages/react-navigation/src/TypeDefinition.js index 2937712a..a7919590 100644 --- a/packages/react-navigation/src/TypeDefinition.js +++ b/packages/react-navigation/src/TypeDefinition.js @@ -262,6 +262,7 @@ export type HeaderProps = { NavigationStackScreenOptions >, style: ViewStyleProp, + isLandscape?: boolean, }; /** diff --git a/packages/react-navigation/src/views/Header/Header.js b/packages/react-navigation/src/views/Header/Header.js index 12f86461..c76d5a73 100644 --- a/packages/react-navigation/src/views/Header/Header.js +++ b/packages/react-navigation/src/views/Header/Header.js @@ -9,6 +9,7 @@ import { Animated, Platform, StyleSheet, View } from 'react-native'; import HeaderTitle from './HeaderTitle'; import HeaderBackButton from './HeaderBackButton'; import HeaderStyleInterpolator from './HeaderStyleInterpolator'; +import withOrientation from '../withOrientation'; import type { NavigationScene, @@ -281,14 +282,25 @@ class Header extends React.PureComponent { screenProps, progress, style, + isLandscape, ...rest } = this.props; const { options } = this.props.getScreenDetails(scene); const headerStyle = options.headerStyle; + const landscapeAwareStatusBarHeight = isLandscape ? 0 : STATUSBAR_HEIGHT; + const containerStyles = [ + styles.container, + { + paddingTop: landscapeAwareStatusBarHeight, + height: APPBAR_HEIGHT + landscapeAwareStatusBarHeight, + }, + headerStyle, + style, + ]; return ( - + {appBar} ); @@ -315,9 +327,7 @@ if (Platform.OS === 'ios') { const styles = StyleSheet.create({ container: { - paddingTop: STATUSBAR_HEIGHT, backgroundColor: Platform.OS === 'ios' ? '#F7F7F7' : '#FFF', - height: STATUSBAR_HEIGHT + APPBAR_HEIGHT, ...platformContainerStyles, }, appBar: { @@ -353,4 +363,4 @@ const styles = StyleSheet.create({ }, }); -export default Header; +export default withOrientation(Header); diff --git a/packages/react-navigation/src/views/__tests__/__snapshots__/withOrientation-test.js.snap b/packages/react-navigation/src/views/__tests__/__snapshots__/withOrientation-test.js.snap new file mode 100644 index 00000000..70cd536a --- /dev/null +++ b/packages/react-navigation/src/views/__tests__/__snapshots__/withOrientation-test.js.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`it adds isLandscape to props 1`] = ` + +`; diff --git a/packages/react-navigation/src/views/__tests__/withOrientation-test.js b/packages/react-navigation/src/views/__tests__/withOrientation-test.js new file mode 100644 index 00000000..0240ae8a --- /dev/null +++ b/packages/react-navigation/src/views/__tests__/withOrientation-test.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { View } from 'react-native'; +import renderer from 'react-test-renderer'; +import withOrientation, { isOrientationLandscape } from '../withOrientation'; + +test('it adds isLandscape to props', () => { + const WrappedComponent = withOrientation(View); + const rendered = renderer.create().toJSON(); + expect(rendered).toMatchSnapshot(); +}); + +test('calculates orientation correctly', () => { + const isLandscape = isOrientationLandscape({ width: 10, height: 1 }); + expect(isLandscape).toBeTruthy(); +}); diff --git a/packages/react-navigation/src/views/withOrientation.js b/packages/react-navigation/src/views/withOrientation.js new file mode 100644 index 00000000..9a7d81ae --- /dev/null +++ b/packages/react-navigation/src/views/withOrientation.js @@ -0,0 +1,55 @@ +// @flow + +import React from 'react'; +import { Dimensions } from 'react-native'; +import hoistNonReactStatic from 'hoist-non-react-statics'; + +type WindowDimensions = { + width: number, + height: number, +}; + +type InjectedProps = { + isLandscape: boolean, +}; + +type State = { + isLandscape: boolean, +}; + +export const isOrientationLandscape = ({ + width, + height, +}: WindowDimensions): boolean => width > height; + +export default function(WrappedComponent: ReactClass) { + class withOrientation extends React.Component { + state: State; + + constructor() { + super(); + + const isLandscape = isOrientationLandscape(Dimensions.get('window')); + this.state = { isLandscape }; + } + + componentDidMount() { + Dimensions.addEventListener('change', this.handleOrientationChange); + } + + componentWillUnmount() { + Dimensions.removeEventListener('change', this.handleOrientationChange); + } + + handleOrientationChange = ({ window }: { window: WindowDimensions }) => { + const isLandscape = isOrientationLandscape(window); + this.setState({ isLandscape }); + }; + + render() { + return ; + } + } + + return hoistNonReactStatic(withOrientation, WrappedComponent); +} diff --git a/packages/react-navigation/yarn.lock b/packages/react-navigation/yarn.lock index b79425ca..9cc94056 100644 --- a/packages/react-navigation/yarn.lock +++ b/packages/react-navigation/yarn.lock @@ -2287,6 +2287,18 @@ fbjs@0.8.12: setimmediate "^1.0.5" ua-parser-js "^0.7.9" +fbjs@^0.8.16: + version "0.8.16" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.9" + fbjs@^0.8.9: version "0.8.15" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.15.tgz#4f0695fdfcc16c37c0b07facec8cb4c4091685b9" @@ -4587,12 +4599,12 @@ react-proxy@^1.1.7: lodash "^4.6.1" react-deep-force-update "^1.0.0" -react-test-renderer@^15.6.1: - version "15.6.1" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-15.6.1.tgz#026f4a5bb5552661fd2cc4bbcd0d4bc8a35ebf7e" +react-test-renderer@^16.0.0: + version "16.0.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.0.0.tgz#9fe7b8308f2f71f29fc356d4102086f131c9cb15" dependencies: - fbjs "^0.8.9" - object-assign "^4.1.0" + fbjs "^0.8.16" + object-assign "^4.1.1" react-timer-mixin@^0.13.2: version "0.13.3"