react-native-gifted-chat-flashlist
Version:
React Native Gifted Chat with FlashList optimization for better performance
115 lines • 4.05 kB
JavaScript
import React, { useCallback, useEffect, useState, useMemo } from 'react';
import { StyleSheet, View } from 'react-native';
import Color from './Color';
import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withDelay, withRepeat, withSequence, withTiming, } from 'react-native-reanimated';
const DotsAnimation = () => {
const dot1 = useSharedValue(0);
const dot2 = useSharedValue(0);
const dot3 = useSharedValue(0);
const topY = useMemo(() => -5, []);
const bottomY = useMemo(() => 5, []);
const duration = useMemo(() => 500, []);
const dot1Style = useAnimatedStyle(() => ({
transform: [{
translateY: dot1.value,
}],
}), [dot1]);
const dot2Style = useAnimatedStyle(() => ({
transform: [{
translateY: dot2.value,
}],
}), [dot2]);
const dot3Style = useAnimatedStyle(() => ({
transform: [{
translateY: dot3.value,
}],
}), [dot3]);
useEffect(() => {
dot1.value = withRepeat(withSequence(withTiming(topY, { duration }), withTiming(bottomY, { duration })), 0, true);
}, [dot1, topY, bottomY, duration]);
useEffect(() => {
dot2.value = withDelay(100, withRepeat(withSequence(withTiming(topY, { duration }), withTiming(bottomY, { duration })), 0, true));
}, [dot2, topY, bottomY, duration]);
useEffect(() => {
dot3.value = withDelay(200, withRepeat(withSequence(withTiming(topY, { duration }), withTiming(bottomY, { duration })), 0, true));
}, [dot3, topY, bottomY, duration]);
return (<View style={styles.dots}>
<Animated.View style={[styles.dot, dot1Style]}/>
<Animated.View style={[styles.dot, dot2Style]}/>
<Animated.View style={[styles.dot, dot3Style]}/>
</View>);
};
const TypingIndicator = ({ isTyping }) => {
const yCoords = useSharedValue(200);
const heightScale = useSharedValue(0);
const marginScale = useSharedValue(0);
const [isVisible, setIsVisible] = useState(isTyping);
const containerStyle = useAnimatedStyle(() => ({
transform: [
{
translateY: yCoords.value,
},
],
height: heightScale.value,
marginBottom: marginScale.value,
}), [yCoords, heightScale, marginScale]);
const slideIn = useCallback(() => {
const duration = 250;
yCoords.value = withTiming(0, { duration });
heightScale.value = withTiming(35, { duration });
marginScale.value = withTiming(8, { duration });
}, [yCoords, heightScale, marginScale]);
// side effect
const slideOut = useCallback(() => {
const duration = 250;
yCoords.value = withTiming(200, { duration });
heightScale.value = withTiming(0, { duration });
marginScale.value = withTiming(0, { duration }, isFinished => {
if (isFinished)
runOnJS(setIsVisible)(false);
});
}, [yCoords, heightScale, marginScale]);
useEffect(() => {
if (isVisible)
if (isTyping)
slideIn();
else
slideOut();
}, [isVisible, isTyping, slideIn, slideOut]);
useEffect(() => {
if (isTyping)
setIsVisible(true);
}, [isTyping]);
if (!isVisible)
return null;
return (<Animated.View style={[
styles.container,
containerStyle,
]}>
<DotsAnimation />
</Animated.View>);
};
const styles = StyleSheet.create({
container: {
marginLeft: 8,
width: 45,
borderRadius: 15,
backgroundColor: Color.leftBubbleBackground,
},
dots: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
dot: {
marginLeft: 2,
marginRight: 2,
borderRadius: 4,
width: 8,
height: 8,
backgroundColor: 'rgba(0, 0, 0, 0.38)',
},
});
export default TypingIndicator;
//# sourceMappingURL=TypingIndicator.js.map