diff --git a/packages/stack/package.json b/packages/stack/package.json index 6b8c5746..2395292f 100644 --- a/packages/stack/package.json +++ b/packages/stack/package.json @@ -45,7 +45,7 @@ "devDependencies": { "@react-native-community/bob": "^0.10.0", "@react-native-community/masked-view": "^0.1.7", - "@react-navigation/stack": "^5.6.0", + "@react-navigation/stack": "^5.6.1", "@types/color": "^3.0.1", "@types/react": "^16.9.23", "@types/react-native": "^0.61.22", diff --git a/packages/stack/scripts/stack.patch b/packages/stack/scripts/stack.patch index 30c77120..19c342d1 100644 --- a/packages/stack/scripts/stack.patch +++ b/packages/stack/scripts/stack.patch @@ -1,5 +1,5 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/index.tsx src/vendor/index.tsx ---- ../../node_modules/@react-navigation/stack/src/index.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/index.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/index.tsx 2020-06-24 23:16:17.000000000 +0200 @@ -3,11 +3,6 @@ import * as TransitionSpecs from './TransitionConfigs/TransitionSpecs'; @@ -28,7 +28,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/index.tsx src/vendor/i StackHeaderLeftButtonProps, StackHeaderTitleProps, diff -Naur ../../node_modules/@react-navigation/stack/src/navigators/createStackNavigator.tsx src/vendor/navigators/createStackNavigator.tsx ---- ../../node_modules/@react-navigation/stack/src/navigators/createStackNavigator.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/navigators/createStackNavigator.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/navigators/createStackNavigator.tsx 1970-01-01 01:00:00.000000000 +0100 @@ -1,96 +0,0 @@ -import * as React from 'react'; @@ -128,7 +128,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/navigators/createStack - typeof StackNavigator ->(StackNavigator); diff -Naur ../../node_modules/@react-navigation/stack/src/types.tsx src/vendor/types.tsx ---- ../../node_modules/@react-navigation/stack/src/types.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/types.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/types.tsx 2020-06-24 23:18:40.000000000 +0200 @@ -8,15 +8,28 @@ } from 'react-native'; @@ -262,7 +262,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/types.tsx src/vendor/t export type StackNavigationConfig = { diff -Naur ../../node_modules/@react-navigation/stack/src/utils/PreviousSceneContext.tsx src/vendor/utils/PreviousSceneContext.tsx ---- ../../node_modules/@react-navigation/stack/src/utils/PreviousSceneContext.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/utils/PreviousSceneContext.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/utils/PreviousSceneContext.tsx 2020-06-24 23:26:38.000000000 +0200 @@ -1,6 +1,5 @@ import * as React from 'react'; @@ -273,8 +273,8 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/utils/PreviousSceneCon const PreviousSceneContext = React.createContext< Scene> | undefined diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/Header.tsx src/vendor/views/Header/Header.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Header/Header.tsx 2020-06-24 23:11:52.000000000 +0200 -+++ src/vendor/views/Header/Header.tsx 2020-06-24 23:33:25.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Header/Header.tsx 2020-06-25 01:58:50.000000000 +0200 ++++ src/vendor/views/Header/Header.tsx 2020-06-25 03:01:13.000000000 +0200 @@ -1,12 +1,15 @@ import * as React from 'react'; -import { StackActions } from '@react-navigation/native'; @@ -303,7 +303,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/Header.ts let leftLabel; -@@ -38,17 +41,18 @@ +@@ -38,17 +41,20 @@ ? o.headerTitle : o.title !== undefined ? o.title @@ -319,16 +319,18 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/Header.ts - ...StackActions.pop(), - source: scene.route.key, - }); -+ if (navigation.isFirstRouteInParent()) { -+ // If we're the first route, we're going back to a parent navigator -+ // So we can't specify a key here -+ navigation.dispatch(StackActions.pop()); -+ } else { -+ navigation.dispatch(StackActions.pop({ key: scene.route.key })); ++ const key = navigation.isFirstRouteInParent() ++ ? // If we're the first route, we're going back to a parent navigator ++ // So we need to get the key of the route we're nested in ++ navigation.dangerouslyGetParent()?.state.key ++ : scene.route.key; ++ ++ if (key !== undefined) { ++ navigation.dispatch(StackActions.pop({ key })); } }, 50), [navigation, scene.route.key] -@@ -64,7 +68,10 @@ +@@ -64,7 +70,10 @@ leftLabel={leftLabel} headerTitle={ typeof options.headerTitle !== 'function' @@ -340,7 +342,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/Header.ts : options.headerTitle } onGoBack={previous ? goBack : undefined} -@@ -72,3 +79,18 @@ +@@ -72,3 +81,18 @@ /> ); }); @@ -360,7 +362,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/Header.ts + +export default Header; diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderBackButton.tsx src/vendor/views/Header/HeaderBackButton.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderBackButton.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderBackButton.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Header/HeaderBackButton.tsx 2020-06-24 23:21:49.000000000 +0200 @@ -8,9 +8,9 @@ StyleSheet, @@ -374,7 +376,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderBac type Props = StackHeaderLeftButtonProps; diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderBackground.tsx src/vendor/views/Header/HeaderBackground.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderBackground.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderBackground.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Header/HeaderBackground.tsx 2020-06-24 23:16:23.000000000 +0200 @@ -7,7 +7,7 @@ StyleProp, @@ -386,7 +388,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderBac type Props = ViewProps & { style?: Animated.WithAnimatedValue>; diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderContainer.tsx src/vendor/views/Header/HeaderContainer.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderContainer.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderContainer.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Header/HeaderContainer.tsx 2020-06-24 23:21:29.000000000 +0200 @@ -1,11 +1,6 @@ import * as React from 'react'; @@ -439,7 +441,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderCon ); })} diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderSegment.tsx src/vendor/views/Header/HeaderSegment.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderSegment.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderSegment.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Header/HeaderSegment.tsx 2020-06-24 23:20:58.000000000 +0200 @@ -8,7 +8,7 @@ ViewStyle, @@ -460,7 +462,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderSeg }; diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderTitle.tsx src/vendor/views/Header/HeaderTitle.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderTitle.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Header/HeaderTitle.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Header/HeaderTitle.tsx 2020-06-24 23:16:23.000000000 +0200 @@ -1,6 +1,6 @@ import * as React from 'react'; @@ -471,7 +473,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Header/HeaderTit type Props = Omit, 'key'> & { tintColor?: string; diff -Naur ../../node_modules/@react-navigation/stack/src/views/Stack/Card.tsx src/vendor/views/Stack/Card.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Stack/Card.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Stack/Card.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Stack/Card.tsx 2020-06-24 23:16:23.000000000 +0200 @@ -146,7 +146,7 @@ @@ -483,7 +485,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Stack/Card.tsx s private animate = ({ closing, diff -Naur ../../node_modules/@react-navigation/stack/src/views/Stack/CardContainer.tsx src/vendor/views/Stack/CardContainer.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Stack/CardContainer.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Stack/CardContainer.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Stack/CardContainer.tsx 2020-06-24 23:20:38.000000000 +0200 @@ -1,12 +1,13 @@ import * as React from 'react'; @@ -501,7 +503,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Stack/CardContai Layout, StackHeaderMode, diff -Naur ../../node_modules/@react-navigation/stack/src/views/Stack/CardStack.tsx src/vendor/views/Stack/CardStack.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Stack/CardStack.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Stack/CardStack.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Stack/CardStack.tsx 2020-06-24 23:20:16.000000000 +0200 @@ -7,7 +7,7 @@ Platform, @@ -521,7 +523,7 @@ diff -Naur ../../node_modules/@react-navigation/stack/src/views/Stack/CardStack. StackDescriptorMap, StackNavigationOptions, diff -Naur ../../node_modules/@react-navigation/stack/src/views/Stack/StackView.tsx src/vendor/views/Stack/StackView.tsx ---- ../../node_modules/@react-navigation/stack/src/views/Stack/StackView.tsx 2020-06-24 23:11:52.000000000 +0200 +--- ../../node_modules/@react-navigation/stack/src/views/Stack/StackView.tsx 2020-06-25 01:58:50.000000000 +0200 +++ src/vendor/views/Stack/StackView.tsx 2020-06-24 23:19:46.000000000 +0200 @@ -2,11 +2,11 @@ import { View, Platform, StyleSheet } from 'react-native'; diff --git a/packages/stack/src/vendor/views/Header/HeaderContainer.tsx b/packages/stack/src/vendor/views/Header/HeaderContainer.tsx index da1c905c..96d10f7a 100644 --- a/packages/stack/src/vendor/views/Header/HeaderContainer.tsx +++ b/packages/stack/src/vendor/views/Header/HeaderContainer.tsx @@ -28,7 +28,6 @@ export type Props = { scenes: (Scene> | undefined)[]; getPreviousScene: (props: { route: Route; - index: number; }) => Scene> | undefined; getFocusedRoute: () => Route; onContentHeightChange?: (props: { @@ -75,10 +74,7 @@ export default function HeaderContainer({ const isFocused = focusedRoute.key === scene.route.key; const previous = - getPreviousScene({ - route: scene.route, - index: i, - }) ?? parentPreviousScene; + getPreviousScene({ route: scene.route }) ?? parentPreviousScene; // If the screen is next to a headerless screen, we need to make the header appear static // This makes the header look like it's moving with the screen diff --git a/packages/stack/src/vendor/views/Header/HeaderContainer.tsx.orig b/packages/stack/src/vendor/views/Header/HeaderContainer.tsx.orig new file mode 100644 index 00000000..d31829c5 --- /dev/null +++ b/packages/stack/src/vendor/views/Header/HeaderContainer.tsx.orig @@ -0,0 +1,170 @@ +import * as React from 'react'; +import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native'; +import { + NavigationContext, + NavigationRouteContext, + Route, + ParamListBase, +} from '@react-navigation/native'; +import type { EdgeInsets } from 'react-native-safe-area-context'; + +import Header from './Header'; +import { + forSlideLeft, + forSlideUp, + forNoAnimation, + forSlideRight, +} from '../../TransitionConfigs/HeaderStyleInterpolators'; +import HeaderShownContext from '../../utils/HeaderShownContext'; +import PreviousSceneContext from '../../utils/PreviousSceneContext'; +import type { + Layout, + Scene, + StackHeaderStyleInterpolator, + StackNavigationProp, + GestureDirection, +} from '../../types'; + +export type Props = { + mode: 'float' | 'screen'; + layout: Layout; + insets: EdgeInsets; + scenes: (Scene> | undefined)[]; + getPreviousScene: (props: { + route: Route; + }) => Scene> | undefined; + getFocusedRoute: () => Route; + onContentHeightChange?: (props: { + route: Route; + height: number; + }) => void; + styleInterpolator: StackHeaderStyleInterpolator; + gestureDirection: GestureDirection; + style?: StyleProp; +}; + +export default function HeaderContainer({ + mode, + scenes, + layout, + insets, + getPreviousScene, + getFocusedRoute, + onContentHeightChange, + gestureDirection, + styleInterpolator, + style, +}: Props) { + const focusedRoute = getFocusedRoute(); + const isParentHeaderShown = React.useContext(HeaderShownContext); + const parentPreviousScene = React.useContext(PreviousSceneContext); + + return ( + + {scenes.slice(-3).map((scene, i, self) => { + if ((mode === 'screen' && i !== self.length - 1) || !scene) { + return null; + } + + const { + header, + headerShown = isParentHeaderShown === false, + headerTransparent, + } = scene.descriptor.options || {}; + + if (!headerShown) { + return null; + } + + const isFocused = focusedRoute.key === scene.route.key; + const previous = + getPreviousScene({ route: scene.route }) ?? parentPreviousScene; + + // If the screen is next to a headerless screen, we need to make the header appear static + // This makes the header look like it's moving with the screen + const previousScene = self[i - 1]; + const nextScene = self[i + 1]; + + const { + headerShown: previousHeaderShown = isParentHeaderShown === false, + } = previousScene?.descriptor.options || {}; + + const { headerShown: nextHeaderShown = isParentHeaderShown === false } = + nextScene?.descriptor.options || {}; + + const isHeaderStatic = + (previousHeaderShown === false && + // We still need to animate when coming back from next scene + // A hacky way to check this is if the next scene exists + !nextScene) || + nextHeaderShown === false; + + const props = { + mode, + layout, + insets, + scene, + previous, + navigation: scene.descriptor.navigation as StackNavigationProp< + ParamListBase + >, + styleInterpolator: + mode === 'float' + ? isHeaderStatic + ? gestureDirection === 'vertical' || + gestureDirection === 'vertical-inverted' + ? forSlideUp + : gestureDirection === 'horizontal-inverted' + ? forSlideRight + : forSlideLeft + : styleInterpolator + : forNoAnimation, + }; + + return ( + + + + onContentHeightChange({ + route: scene.route, + height: e.nativeEvent.layout.height, + }) + : undefined + } + pointerEvents={isFocused ? 'box-none' : 'none'} + accessibilityElementsHidden={!isFocused} + importantForAccessibility={ + isFocused ? 'auto' : 'no-hide-descendants' + } + style={ + // Avoid positioning the focused header absolutely + // Otherwise accessibility tools don't seem to be able to find it + (mode === 'float' && !isFocused) || headerTransparent + ? styles.header + : null + } + > + {header !== undefined ? header(props) :
} + + + + ); + })} + + ); +} + +const styles = StyleSheet.create({ + header: { + position: 'absolute', + top: 0, + left: 0, + right: 0, + }, +}); diff --git a/packages/stack/src/vendor/views/Stack/CardContainer.tsx b/packages/stack/src/vendor/views/Stack/CardContainer.tsx index 817149e9..eedefa70 100644 --- a/packages/stack/src/vendor/views/Stack/CardContainer.tsx +++ b/packages/stack/src/vendor/views/Stack/CardContainer.tsx @@ -33,7 +33,6 @@ type Props = TransitionPreset & { cardStyle?: StyleProp; getPreviousScene: (props: { route: Route; - index: number; }) => Scene> | undefined; getFocusedRoute: () => Route; renderHeader: (props: HeaderContainerProps) => React.ReactNode; @@ -163,7 +162,7 @@ function CardContainer({ const isParentHeaderShown = React.useContext(HeaderShownContext); const isCurrentHeaderShown = headerMode !== 'none' && headerShown !== false; - const previousScene = getPreviousScene({ route: scene.route, index }); + const previousScene = getPreviousScene({ route: scene.route }); return ( { return state.routes[state.index]; }; - private getPreviousScene = ({ - route, - index, - }: { - route: Route; - index: number; - }) => { - const previousRoute = this.props.getPreviousRoute({ route }); + private getPreviousScene = ({ route }: { route: Route }) => { + const { getPreviousRoute } = this.props; + const { scenes } = this.state; - let previous: Scene> | undefined; + const previousRoute = getPreviousRoute({ route }); if (previousRoute) { - // The previous scene will be shortly before the current scene in the array - // So loop back from current index to avoid looping over the full array - for (let j = index - 1; j >= 0; j--) { - const s = this.state.scenes[j]; + const previousScene = scenes.find( + (scene) => scene.route.key === previousRoute.key + ); - if (s && s.route.key === previousRoute.key) { - previous = s; - break; - } - } + return previousScene; } - return previous; + return undefined; }; render() { diff --git a/yarn.lock b/yarn.lock index 72391629..26d48ea2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3202,10 +3202,10 @@ resolved "https://registry.yarnpkg.com/@react-native-community/masked-view/-/masked-view-0.1.7.tgz#a65ce0702f55cb67fd777995de6fc7b3e5781903" integrity sha512-9KbP7LTLFz9dx1heURJbO6nuVMdSjDez8znlrUzaB1nUwKVsTTwlKRuHxGUYIIkReLWrJQeCv9tidy+84z2eCw== -"@react-navigation/stack@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-5.6.0.tgz#c307559ab6ba380f977f7f74efbe861bcbbdcf4b" - integrity sha512-e5uU37qgi9cXqOac8P2oFAj+4ZY7dI2kt04jg5+psAYN0Coawk6oyowBpBy6FsMBHMQv/p8J97Hc6eUnTwgzQw== +"@react-navigation/stack@^5.6.1": + version "5.6.1" + resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-5.6.1.tgz#9cdb64cfa1b8fc3d9c7204589effce7278bf6d2e" + integrity sha512-pbiNHKGa+7awvh+mjuvU6L05s/6qYxxs+4tY5ldCsMrqP+PoYW8/avY0lJBaByAfTZmJbHAZrtcC+rFic8NAnA== dependencies: color "^3.1.2" react-native-iphone-x-helper "^1.2.1"