Skip to content

Commit b9aed8e

Browse files
committed
fix animation using navigation
1 parent 09794bf commit b9aed8e

3 files changed

Lines changed: 51 additions & 58 deletions

File tree

src/components/Accordion/index.tsx

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type {StyleProp, ViewStyle} from 'react-native';
44
import {View} from 'react-native';
55
import type {SharedValue} from 'react-native-reanimated';
66
import Animated, {Easing, useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
7-
import useThemeStyles from '@hooks/useThemeStyles';
87

98
type AccordionProps = {
109
/** Giving information whether the component is open */
@@ -19,48 +18,52 @@ type AccordionProps = {
1918
/** Additional external style */
2019
style?: StyleProp<ViewStyle>;
2120

22-
/** Should active animation */
23-
shouldActiveAnimation?: React.RefObject<boolean>;
21+
/** Was toggle triggered */
22+
isToggleTriggered: React.MutableRefObject<boolean>;
2423
};
2524

26-
function Accordion({isExpanded, children, duration = 300, style, shouldActiveAnimation = React.useRef(true)}: AccordionProps) {
25+
function Accordion({isExpanded, children, duration = 300, style, isToggleTriggered}: AccordionProps) {
2726
const height = useSharedValue(0);
28-
const styles = useThemeStyles();
2927

30-
const derivedHeight = useDerivedValue(() =>
31-
shouldActiveAnimation.current
32-
? withTiming(height.get() * Number(isExpanded.get()), {
33-
duration,
34-
easing: Easing.inOut(Easing.quad),
35-
})
36-
: height.get() * Number(isExpanded.get()),
37-
);
28+
const derivedHeight = useDerivedValue(() => {
29+
if (!isToggleTriggered.current) {
30+
return isExpanded.get() ? height.get() : 0;
31+
}
32+
33+
return withTiming(height.get() * Number(isExpanded.get()), {
34+
duration,
35+
easing: Easing.inOut(Easing.quad),
36+
});
37+
});
3838

3939
const derivedOpacity = useDerivedValue(() => {
40-
if (shouldActiveAnimation.current) {
41-
return withTiming(isExpanded.get() ? 1 : 0, {
42-
duration,
43-
easing: Easing.inOut(Easing.quad),
44-
});
40+
if (!isToggleTriggered.current) {
41+
return isExpanded.get() ? 1 : 0;
4542
}
46-
return isExpanded.get() ? 1 : 0;
43+
44+
return withTiming(isExpanded.get() ? 1 : 0, {
45+
duration,
46+
easing: Easing.inOut(Easing.quad),
47+
});
4748
});
4849

49-
const bodyStyle = useAnimatedStyle(() => ({
50-
height: derivedHeight.get(),
51-
opacity: derivedOpacity.get(),
52-
}));
50+
const animatedStyle = useAnimatedStyle(() => {
51+
if (!isToggleTriggered.current && !isExpanded.get()) {
52+
return {
53+
height: 0,
54+
opacity: 0,
55+
};
56+
}
57+
58+
return {
59+
height: !isToggleTriggered.current ? undefined : derivedHeight.get(),
60+
opacity: derivedOpacity.get(),
61+
};
62+
});
5363

5464
return (
55-
<Animated.View style={[bodyStyle, style]}>
56-
<View
57-
onLayout={(e) => {
58-
height.set(e.nativeEvent.layout.height);
59-
}}
60-
style={[styles.pAbsolute, styles.l0, styles.r0, styles.t0]}
61-
>
62-
{children}
63-
</View>
65+
<Animated.View style={[style, animatedStyle]}>
66+
<View onLayout={(e) => height.set(e.nativeEvent.layout.height)}>{children}</View>
6467
</Animated.View>
6568
);
6669
}

src/libs/Navigation/linkTo/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,13 @@ export default function linkTo(navigation: NavigationContainerRef<RootStackParam
184184
}
185185
}
186186

187-
if (action && 'payload' in action && action.payload && 'name' in action.payload && isSideModalNavigator(action.payload.name)) {
187+
if (
188+
action &&
189+
'payload' in action &&
190+
action.payload &&
191+
'name' in action.payload &&
192+
(isSideModalNavigator(action.payload.name) || action.payload.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR)
193+
) {
188194
// Information about the state may be in the params.
189195
const currentFocusedRoute = findFocusedRoute(extrapolateStateFromParams(rootState));
190196
const targetFocusedRoute = findFocusedRoute(stateFromPath);
@@ -202,7 +208,7 @@ export default function linkTo(navigation: NavigationContainerRef<RootStackParam
202208
// There are situations where a route already exists on the current navigation stack
203209
// But we want to push the same route instead of going back in the stack
204210
// Which would break the user navigation history
205-
if (!isActiveRoute && type === CONST.NAVIGATION.ACTION_TYPE.PUSH) {
211+
if ((!isActiveRoute && type === CONST.NAVIGATION.ACTION_TYPE.PUSH) || action.payload.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR) {
206212
minimalAction.type = CONST.NAVIGATION.ACTION_TYPE.PUSH;
207213
}
208214
root.dispatch(minimalAction);

src/pages/workspace/workflows/ToggleSettingsOptionRow.tsx

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type {ReactNode} from 'react';
2-
import React, {useEffect, useMemo, useState} from 'react';
2+
import React, {useEffect, useMemo} from 'react';
33
import {View} from 'react-native';
4-
import type {LayoutChangeEvent, StyleProp, TextStyle, ViewStyle} from 'react-native';
4+
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
55
import {useSharedValue} from 'react-native-reanimated';
66
import Accordion from '@components/Accordion';
77
import Icon from '@components/Icon';
@@ -105,25 +105,12 @@ function ToggleSettingOptionRow({
105105
}: ToggleSettingOptionRowProps) {
106106
const styles = useThemeStyles();
107107
const isExpanded = useSharedValue(isActive);
108-
const shouldActiveAnimation = React.useRef(false);
109-
const [isVisible, setIsVisible] = useState(false); // State to track visibility
108+
const isToggleTriggered = React.useRef(false);
110109

111110
useEffect(() => {
112111
isExpanded.set(isActive);
113112
}, [isExpanded, isActive]);
114113

115-
const handleVisibilityChange = (e: LayoutChangeEvent) => {
116-
const {height, y} = e.nativeEvent.layout;
117-
const isInViewport = y + height > 0 && y < height; // Check if the element is in the viewport
118-
119-
if (isInViewport && !isVisible) {
120-
setIsVisible(true);
121-
} else if (!isInViewport && isVisible) {
122-
setIsVisible(false);
123-
shouldActiveAnimation.current = false; // Set to false when it's not visible
124-
}
125-
};
126-
127114
const subtitleHtml = useMemo(() => {
128115
if (!subtitle || !shouldParseSubtitle || typeof subtitle !== 'string') {
129116
return '';
@@ -175,10 +162,7 @@ function ToggleSettingOptionRow({
175162
style={[wrapperStyle]}
176163
onClose={onCloseError}
177164
>
178-
<View
179-
style={styles.pRelative}
180-
onLayout={handleVisibilityChange}
181-
>
165+
<View style={styles.pRelative}>
182166
<View style={[styles.flexRow, styles.alignItemsCenter, styles.justifyContentBetween]}>
183167
<View style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]}>
184168
{!!icon && (
@@ -199,9 +183,9 @@ function ToggleSettingOptionRow({
199183
<Switch
200184
disabledAction={disabledAction}
201185
accessibilityLabel={switchAccessibilityLabel}
202-
onToggle={(isEnabled) => {
203-
onToggle(isEnabled);
204-
shouldActiveAnimation.current = true;
186+
onToggle={(isOn) => {
187+
isToggleTriggered.current = true;
188+
onToggle(isOn);
205189
}}
206190
isOn={isActive}
207191
disabled={disabled}
@@ -212,7 +196,7 @@ function ToggleSettingOptionRow({
212196
<Accordion
213197
isExpanded={isExpanded}
214198
style={accordionStyle}
215-
shouldActiveAnimation={shouldActiveAnimation}
199+
isToggleTriggered={isToggleTriggered}
216200
>
217201
{subMenuItems}
218202
</Accordion>

0 commit comments

Comments
 (0)