Skip to content

Commit d03ffdb

Browse files
authored
Fix/incubator dialog no measure 2 (#2282)
* IncubatorDialog - fix no measure occurring * IncubatorDialog - fix enter animation
1 parent be085bb commit d03ffdb

File tree

5 files changed

+62
-37
lines changed

5 files changed

+62
-37
lines changed

src/incubator/Dialog/index.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import Modal from '../../components/modal';
1111
import {extractAlignmentsValues} from '../../commons/modifiers';
1212
import useHiddenLocation from '../hooks/useHiddenLocation';
1313
import usePanGesture from '../panView/usePanGesture';
14-
import useAnimatedTransition, {TransitionViewAnimationType} from './useAnimatedTransition';
14+
import useAnimatedTransition, {AnimatedTransitionProps, TransitionViewAnimationType} from './useAnimatedTransition';
1515
import DialogHeader from './DialogHeader';
1616
import {DialogProps, DialogDirections, DialogDirectionsEnum, DialogHeaderProps} from './types';
1717
export {DialogProps, DialogDirections, DialogDirectionsEnum, DialogHeaderProps};
1818
import useFadeView from './useFadeView';
1919

20+
const TRANSITION_ANIMATION_DELAY: AnimatedTransitionProps['delay'] = {enter: 100};
21+
2022
export interface DialogStatics {
2123
directions: typeof DialogDirectionsEnum;
2224
Header: typeof DialogHeader;
@@ -40,7 +42,6 @@ const Dialog = (props: DialogProps) => {
4042
const {overlayBackgroundColor, ...otherModalProps} = modalProps;
4143
const initialVisibility = useRef(propsVisibility);
4244
const [visible, setVisible] = useState(propsVisibility);
43-
const containerRef = React.createRef<RNView>();
4445
const opacity = useSharedValue<number>(Number(propsVisibility));
4546

4647
const directions = useMemo((): DialogDirections[] => {
@@ -67,7 +68,7 @@ const Dialog = (props: DialogProps) => {
6768
},
6869
[onDismiss, setVisible]);
6970

70-
const {onLayout, hiddenLocation} = useHiddenLocation({containerRef});
71+
const {setRef, onLayout, hiddenLocation} = useHiddenLocation<RNView>();
7172

7273
const {
7374
translation: panTranslation,
@@ -98,7 +99,8 @@ const Dialog = (props: DialogProps) => {
9899
enterFrom: direction,
99100
exitTo: direction,
100101
onAnimationStart: fade,
101-
onAnimationEnd: onTransitionAnimationEnd
102+
onAnimationEnd: onTransitionAnimationEnd,
103+
delay: TRANSITION_ANIMATION_DELAY
102104
});
103105

104106
const open = useCallback(() => {
@@ -159,7 +161,7 @@ const Dialog = (props: DialogProps) => {
159161
const renderDialog = () => {
160162
return (
161163
<PanGestureHandler onGestureEvent={isEmpty(directions) ? undefined : panGestureEvent}>
162-
<View reanimated style={style} onLayout={onLayout} ref={containerRef} testID={testID}>
164+
<View reanimated style={style} onLayout={onLayout} ref={setRef} testID={testID}>
163165
<DialogHeader {...headerProps}/>
164166
{children}
165167
</View>

src/incubator/Dialog/useAnimatedTransition.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable react-hooks/exhaustive-deps */
22
import {useEffect, useCallback} from 'react';
3-
import {runOnJS, useSharedValue, withSpring, withTiming} from 'react-native-reanimated';
4-
import {HiddenLocation} from '../hooks/useHiddenLocation';
3+
import {runOnJS, useSharedValue, withSpring, withTiming, withDelay} from 'react-native-reanimated';
4+
import type {HiddenLocation} from '../hooks/useHiddenLocation';
55
import {PanningDirections, PanningDirectionsEnum, DEFAULT_ANIMATION_CONFIG} from '../panView';
66
import useAnimationEndNotifier, {
77
AnimationNotifierEndProps,
@@ -11,6 +11,11 @@ const TransitionViewDirectionEnum = PanningDirectionsEnum;
1111
type TransitionViewDirection = PanningDirections;
1212
export {TransitionViewAnimationType, TransitionViewDirectionEnum, TransitionViewDirection};
1313

14+
interface Delay {
15+
enter?: number;
16+
exit?: number;
17+
}
18+
1419
export interface AnimatedTransitionProps extends AnimationNotifierEndProps {
1520
/**
1621
* Callback to the animation start.
@@ -24,12 +29,16 @@ export interface AnimatedTransitionProps extends AnimationNotifierEndProps {
2429
* If this is given there will be an exit animation to this direction.
2530
*/
2631
exitTo?: TransitionViewDirection;
32+
/**
33+
* Delay the enter \ exit animation.
34+
*/
35+
delay?: Delay;
2736
hiddenLocation: HiddenLocation;
2837
onInitPosition: () => void;
2938
}
3039

3140
export default function useAnimatedTransition(props: AnimatedTransitionProps) {
32-
const {hiddenLocation, onInitPosition, enterFrom, exitTo, onAnimationStart, onAnimationEnd} = props;
41+
const {hiddenLocation, onInitPosition, enterFrom, exitTo, onAnimationStart, onAnimationEnd, delay} = props;
3342

3443
// Has to start at {0, 0} with {opacity: 0} so layout can be measured
3544
const translationX = useSharedValue<number>(0);
@@ -76,14 +85,15 @@ export default function useAnimatedTransition(props: AnimatedTransitionProps) {
7685

7786
const translateTo = useCallback((to: {x: number; y: number},
7887
animationDirection: TransitionViewDirection,
79-
callback: (isFinished?: boolean) => void) => {
88+
callback: (isFinished?: boolean) => void,
89+
delay = 0) => {
8090
'worklet';
8191
// @ts-expect-error
8292
if ([TransitionViewDirectionEnum.LEFT, TransitionViewDirectionEnum.RIGHT].includes(animationDirection)) {
83-
translationX.value = withSpring(to.x, DEFAULT_ANIMATION_CONFIG, callback);
93+
translationX.value = withDelay(delay, withSpring(to.x, DEFAULT_ANIMATION_CONFIG, callback));
8494
// @ts-expect-error
8595
} else if ([TransitionViewDirectionEnum.UP, TransitionViewDirectionEnum.DOWN].includes(animationDirection)) {
86-
translationY.value = withSpring(to.y, DEFAULT_ANIMATION_CONFIG, callback);
96+
translationY.value = withDelay(delay, withSpring(to.y, DEFAULT_ANIMATION_CONFIG, callback));
8797
}
8898
},
8999
[]);
@@ -95,9 +105,9 @@ export default function useAnimatedTransition(props: AnimatedTransitionProps) {
95105
runOnJS(onAnimationStart)('enter');
96106
}
97107

98-
translateTo({x: 0, y: 0}, enterFrom, onEnterAnimationEnd);
108+
translateTo({x: 0, y: 0}, enterFrom, onEnterAnimationEnd, delay?.enter);
99109
}
100-
}, [onEnterAnimationEnd]);
110+
}, [onEnterAnimationEnd, delay?.enter]);
101111

102112
const animateOut = useCallback(() => {
103113
'worklet';
@@ -106,9 +116,9 @@ export default function useAnimatedTransition(props: AnimatedTransitionProps) {
106116
runOnJS(onAnimationStart)('exit');
107117
}
108118

109-
translateTo(getLocation(exitTo), exitTo, onExitAnimationEnd);
119+
translateTo(getLocation(exitTo), exitTo, onExitAnimationEnd, delay?.exit);
110120
}
111-
}, [hiddenLocation, exitTo, onExitAnimationEnd]);
121+
}, [hiddenLocation, exitTo, onExitAnimationEnd, delay?.exit]);
112122

113123
return {animateIn, animateOut, translation: {x: translationX, y: translationY}};
114124
}
Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import {RefObject, useCallback, useState} from 'react';
2-
import {View, LayoutChangeEvent} from 'react-native';
1+
import {useCallback, useRef, useState, RefCallback} from 'react';
2+
import {View} from 'react-native';
33
import {Constants} from '../../commons/new';
44
import {PanningDirectionsEnum} from '../panView';
55

@@ -9,13 +9,7 @@ export interface HiddenLocation extends HiddenLocationRecord {
99
wasMeasured: boolean;
1010
}
1111

12-
export interface HiddenLocationProps<T extends View> {
13-
containerRef: RefObject<T>;
14-
}
15-
16-
export default function useHiddenLocation<T extends View>(props: HiddenLocationProps<T>) {
17-
const {containerRef} = props;
18-
12+
export default function useHiddenLocation<T extends View>() {
1913
const getHiddenLocation = ({
2014
x = 0,
2115
y = 0,
@@ -33,17 +27,37 @@ export default function useHiddenLocation<T extends View>(props: HiddenLocationP
3327
};
3428

3529
const [hiddenLocation, setHiddenLocation] = useState<HiddenLocation>(getHiddenLocation({}));
36-
37-
const onLayout = useCallback((event: LayoutChangeEvent) => {
38-
const {width, height} = event.nativeEvent.layout;
39-
if (containerRef.current && !hiddenLocation.wasMeasured) {
40-
containerRef.current.measureInWindow((x: number, y: number) => {
41-
setHiddenLocation(getHiddenLocation({x, y, width, height, wasMeasured: true}));
30+
const ref = useRef<T>();
31+
const wasMeasured = useRef(false);
32+
33+
const measure = useCallback(() => {
34+
if (!wasMeasured.current) {
35+
ref.current?.measureInWindow((x, y, width, height) => {
36+
if (!wasMeasured.current && width > 0 && height > 0) {
37+
wasMeasured.current = true;
38+
setHiddenLocation(getHiddenLocation({
39+
x,
40+
y,
41+
width,
42+
height,
43+
wasMeasured: true
44+
}));
45+
}
4246
});
4347
}
44-
// eslint-disable-next-line react-hooks/exhaustive-deps
48+
}, []);
49+
50+
const setRef: RefCallback<T> = useCallback((node: T) => {
51+
if (node) {
52+
ref.current = node;
53+
measure();
54+
}
4555
},
46-
[containerRef]);
56+
[measure]);
57+
58+
const onLayout = useCallback(() => {
59+
measure();
60+
}, [measure]);
4761

48-
return {onLayout, hiddenLocation};
62+
return {setRef, onLayout, hiddenLocation};
4963
}

src/incubator/panView/index.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ const PanView = (props: Props) => {
4949
...others
5050
} = props;
5151

52-
const containerRef = React.createRef<RNView>();
53-
const {onLayout, hiddenLocation} = useHiddenLocation({containerRef});
52+
const {setRef, onLayout, hiddenLocation} = useHiddenLocation<RNView>();
5453
const {translation, panGestureEvent} = usePanGesture({
5554
directions,
5655
dismissible,
@@ -68,7 +67,7 @@ const PanView = (props: Props) => {
6867
}, []);
6968

7069
return (
71-
<View ref={containerRef} style={containerStyle} onLayout={onLayout}>
70+
<View ref={setRef} style={containerStyle} onLayout={onLayout}>
7271
<PanGestureHandler onGestureEvent={isEmpty(directions) ? undefined : panGestureEvent}>
7372
<View reanimated style={animatedStyle}>
7473
<View {...others}>{children}</View>

src/incubator/panView/usePanGesture.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
getDismissVelocity,
1111
DEFAULT_THRESHOLD
1212
} from './panningUtil';
13-
import {HiddenLocation} from '../hooks/useHiddenLocation';
13+
import type {HiddenLocation} from '../hooks/useHiddenLocation';
1414

1515
export type PanViewDirections = PanningDirections;
1616
export const PanViewDirectionsEnum = PanningDirectionsEnum;

0 commit comments

Comments
 (0)