-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathAnimatedSettlementButton.tsx
99 lines (91 loc) · 4.38 KB
/
AnimatedSettlementButton.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import React, {useCallback, useEffect} from 'react';
import Animated, {runOnJS, useAnimatedStyle, useSharedValue, withDelay, withTiming} from 'react-native-reanimated';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import SettlementButton from '.';
import type SettlementButtonProps from './types';
type AnimatedSettlementButtonProps = SettlementButtonProps & {
isPaidAnimationRunning: boolean;
onAnimationFinish: () => void;
};
function AnimatedSettlementButton({isPaidAnimationRunning, onAnimationFinish, isDisabled, ...settlementButtonProps}: AnimatedSettlementButtonProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const buttonScale = useSharedValue(1);
const buttonOpacity = useSharedValue(1);
const paymentCompleteTextScale = useSharedValue(0);
const paymentCompleteTextOpacity = useSharedValue(1);
const height = useSharedValue<number>(variables.componentSizeNormal);
const buttonMarginTop = useSharedValue<number>(styles.expenseAndReportPreviewTextButtonContainer.gap);
const buttonStyles = useAnimatedStyle(() => ({
transform: [{scale: buttonScale.get()}],
opacity: buttonOpacity.get(),
}));
const paymentCompleteTextStyles = useAnimatedStyle(() => ({
transform: [{scale: paymentCompleteTextScale.get()}],
opacity: paymentCompleteTextOpacity.get(),
position: 'absolute',
alignSelf: 'center',
}));
const containerStyles = useAnimatedStyle(() => ({
height: height.get(),
justifyContent: 'center',
overflow: 'hidden',
marginTop: buttonMarginTop.get(),
}));
const buttonDisabledStyle = isPaidAnimationRunning
? {
opacity: 1,
...styles.cursorDefault,
}
: undefined;
const resetAnimation = useCallback(() => {
buttonScale.set(1);
buttonOpacity.set(1);
paymentCompleteTextScale.set(0);
paymentCompleteTextOpacity.set(1);
height.set(variables.componentSizeNormal);
buttonMarginTop.set(styles.expenseAndReportPreviewTextButtonContainer.gap);
}, [buttonScale, buttonOpacity, paymentCompleteTextScale, paymentCompleteTextOpacity, height, buttonMarginTop, styles.expenseAndReportPreviewTextButtonContainer.gap]);
useEffect(() => {
if (!isPaidAnimationRunning) {
resetAnimation();
return;
}
buttonScale.set(withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}));
buttonOpacity.set(withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}));
paymentCompleteTextScale.set(withTiming(1, {duration: CONST.ANIMATION_PAID_DURATION}));
// Wait for the above animation + 1s delay before hiding the component
const totalDelay = CONST.ANIMATION_PAID_DURATION + CONST.ANIMATION_PAID_BUTTON_HIDE_DELAY;
height.set(
withDelay(
totalDelay,
withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION}, () => runOnJS(onAnimationFinish)()),
),
);
buttonMarginTop.set(withDelay(totalDelay, withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION})));
paymentCompleteTextOpacity.set(withDelay(totalDelay, withTiming(0, {duration: CONST.ANIMATION_PAID_DURATION})));
}, [isPaidAnimationRunning, onAnimationFinish, buttonOpacity, buttonScale, height, paymentCompleteTextOpacity, paymentCompleteTextScale, buttonMarginTop, resetAnimation]);
return (
<Animated.View style={containerStyles}>
{isPaidAnimationRunning && (
<Animated.View style={paymentCompleteTextStyles}>
<Text style={[styles.buttonMediumText]}>{translate('iou.paymentComplete')}</Text>
</Animated.View>
)}
<Animated.View style={buttonStyles}>
<SettlementButton
// eslint-disable-next-line react/jsx-props-no-spreading
{...settlementButtonProps}
isDisabled={isPaidAnimationRunning || isDisabled}
disabledStyle={buttonDisabledStyle}
/>
</Animated.View>
</Animated.View>
);
}
AnimatedSettlementButton.displayName = 'AnimatedSettlementButton';
export default AnimatedSettlementButton;