From 51b1069d51df4b638eda435da65d580a1dbcb233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Osadnik?= Date: Sun, 7 Jul 2019 13:02:48 +0100 Subject: [PATCH] feat: add on transition end callback (#153) --- packages/stack/src/types.tsx | 2 + packages/stack/src/views/Stack/Stack.tsx | 41 +++++++++++++++----- packages/stack/src/views/Stack/StackItem.tsx | 38 ++++++++++++------ packages/stack/src/views/Stack/StackView.tsx | 4 +- 4 files changed, 61 insertions(+), 24 deletions(-) diff --git a/packages/stack/src/types.tsx b/packages/stack/src/types.tsx index c7716cf3..51b7fe8f 100644 --- a/packages/stack/src/types.tsx +++ b/packages/stack/src/types.tsx @@ -108,6 +108,8 @@ export type NavigationStackOptions = HeaderOptions & horizontal?: number; }; disableKeyboardHandling?: boolean; + onTransitionStart?: () => void; + onTransitionEnd?: () => void; }; export type NavigationConfig = { diff --git a/packages/stack/src/views/Stack/Stack.tsx b/packages/stack/src/views/Stack/Stack.tsx index 1db9d2f0..07a9f0d0 100755 --- a/packages/stack/src/views/Stack/Stack.tsx +++ b/packages/stack/src/views/Stack/Stack.tsx @@ -46,8 +46,8 @@ type Props = { renderScene: (props: { route: Route }) => React.ReactNode; headerMode: HeaderMode; onTransitionStart?: ( - curr: { index: number }, - prev: { index: number } + current: { index: number }, + previous: { index: number } ) => void; onGestureBegin?: () => void; onGestureCanceled?: () => void; @@ -60,7 +60,7 @@ type State = { scenes: HeaderScene[]; progress: ProgressValues; layout: Layout; - floaingHeaderHeight: number; + floatingHeaderHeight: number; }; const dimensions = Dimensions.get('window'); @@ -171,7 +171,7 @@ export default class Stack extends React.Component { // This is not a great heuristic here. We don't know synchronously // on mount what the header height is so we have just used the most // common cases here. - floaingHeaderHeight: getDefaultHeaderHeight(layout), + floatingHeaderHeight: getDefaultHeaderHeight(layout), }; private handleLayout = (e: LayoutChangeEvent) => { @@ -192,11 +192,32 @@ export default class Stack extends React.Component { private handleFloatingHeaderLayout = (e: LayoutChangeEvent) => { const { height } = e.nativeEvent.layout; - if (height !== this.state.floaingHeaderHeight) { - this.setState({ floaingHeaderHeight: height }); + if (height !== this.state.floatingHeaderHeight) { + this.setState({ floatingHeaderHeight: height }); } }; + private handleTransitionStart = ({ + route, + current, + previous, + }: { + route: Route; + current: { index: number }; + previous: { index: number }; + }) => { + const { onTransitionStart, descriptors } = this.props; + const options = descriptors[route.key].options; + + onTransitionStart && onTransitionStart(current, previous); + options.onTransitionStart && options.onTransitionStart(); + }; + + private handleTransitionEnd = ({ route }: { route: Route }) => { + const options = this.props.descriptors[route.key].options; + options.onTransitionEnd && options.onTransitionEnd(); + }; + render() { const { mode, @@ -212,13 +233,12 @@ export default class Stack extends React.Component { renderHeader, renderScene, headerMode, - onTransitionStart, onGestureBegin, onGestureCanceled, onGestureEnd, } = this.props; - const { scenes, layout, progress, floaingHeaderHeight } = this.state; + const { scenes, layout, progress, floatingHeaderHeight } = this.state; const focusedRoute = navigation.state.routes[navigation.state.index]; const focusedOptions = descriptors[focusedRoute.key].options; @@ -300,7 +320,7 @@ export default class Stack extends React.Component { onGestureCanceled={onGestureCanceled} onGestureEnd={onGestureEnd} gestureResponseDistance={gestureResponseDistance} - floaingHeaderHeight={floaingHeaderHeight} + floatingHeaderHeight={floatingHeaderHeight} hasCustomHeader={header === null} getPreviousRoute={getPreviousRoute} headerMode={headerMode} @@ -309,7 +329,8 @@ export default class Stack extends React.Component { renderScene={renderScene} onOpenRoute={onOpenRoute} onCloseRoute={onCloseRoute} - onTransitionStart={onTransitionStart} + onTransitionStart={this.handleTransitionStart} + onTransitionEnd={this.handleTransitionEnd} onGoBack={onGoBack} direction={direction} transitionSpec={transitionSpec} diff --git a/packages/stack/src/views/Stack/StackItem.tsx b/packages/stack/src/views/Stack/StackItem.tsx index ad057e2b..9f78870d 100644 --- a/packages/stack/src/views/Stack/StackItem.tsx +++ b/packages/stack/src/views/Stack/StackItem.tsx @@ -33,10 +33,12 @@ type Props = TransitionPreset & { onOpenRoute: (props: { route: Route }) => void; onCloseRoute: (props: { route: Route }) => void; onGoBack: (props: { route: Route }) => void; - onTransitionStart?: ( - curr: { index: number }, - prev: { index: number } - ) => void; + onTransitionStart?: (props: { + route: Route; + current: { index: number }; + previous: { index: number }; + }) => void; + onTransitionEnd?: (props: { route: Route }) => void; onGestureBegin?: () => void; onGestureCanceled?: () => void; onGestureEnd?: () => void; @@ -46,22 +48,34 @@ type Props = TransitionPreset & { }; headerMode: HeaderMode; headerTransparent?: boolean; - floaingHeaderHeight: number; + floatingHeaderHeight: number; hasCustomHeader: boolean; }; export default class StackItem extends React.PureComponent { - private handleOpen = () => - this.props.onOpenRoute({ route: this.props.scene.route }); + private handleOpen = () => { + const { scene, onTransitionEnd, onOpenRoute } = this.props; - private handleClose = () => - this.props.onCloseRoute({ route: this.props.scene.route }); + onTransitionEnd && onTransitionEnd({ route: scene.route }); + onOpenRoute({ route: scene.route }); + }; + + private handleClose = () => { + const { scene, onTransitionEnd, onCloseRoute } = this.props; + + onTransitionEnd && onTransitionEnd({ route: scene.route }); + onCloseRoute({ route: scene.route }); + }; private handleTransitionStart = ({ closing }: { closing: boolean }) => { const { index, scene, onTransitionStart, onGoBack } = this.props; onTransitionStart && - onTransitionStart({ index: closing ? index - 1 : index }, { index }); + onTransitionStart({ + route: scene.route, + previous: { index: closing ? index - 1 : index }, + current: { index }, + }); closing && onGoBack({ route: scene.route }); }; @@ -86,7 +100,7 @@ export default class StackItem extends React.PureComponent { onGestureCanceled, onGestureEnd, gestureResponseDistance, - floaingHeaderHeight, + floatingHeaderHeight, hasCustomHeader, getPreviousRoute, headerMode, @@ -126,7 +140,7 @@ export default class StackItem extends React.PureComponent { pointerEvents="box-none" containerStyle={ headerMode === 'float' && !headerTransparent && !hasCustomHeader - ? { marginTop: floaingHeaderHeight } + ? { marginTop: floatingHeaderHeight } : null } contentStyle={cardStyle} diff --git a/packages/stack/src/views/Stack/StackView.tsx b/packages/stack/src/views/Stack/StackView.tsx index 928ecee7..691f4f22 100644 --- a/packages/stack/src/views/Stack/StackView.tsx +++ b/packages/stack/src/views/Stack/StackView.tsx @@ -19,8 +19,8 @@ type Props = { descriptors: Descriptors; navigationConfig: NavigationConfig; onTransitionStart?: ( - curr: { index: number }, - prev: { index: number } + current: { index: number }, + previous: { index: number } ) => void; onGestureBegin?: () => void; onGestureCanceled?: () => void;