Files
cally/components/shared/RefreshButton.tsx
2025-02-02 22:28:40 +01:00

84 lines
2.0 KiB
TypeScript

import React, { useRef, useEffect } from 'react';
import { TouchableOpacity, Animated, Easing } from 'react-native';
import { Feather } from '@expo/vector-icons';
interface RefreshButtonProps {
onRefresh: () => Promise<void>;
isSyncing: boolean;
size?: number;
color?: string;
}
const RefreshButton = ({
onRefresh,
isSyncing,
size = 24,
color = "#83807F"
}: RefreshButtonProps) => {
const rotateAnim = useRef(new Animated.Value(0)).current;
const rotationLoop = useRef<Animated.CompositeAnimation | null>(null);
useEffect(() => {
if (isSyncing) {
startContinuousRotation();
} else {
stopRotation();
}
}, [isSyncing]);
const startContinuousRotation = () => {
rotateAnim.setValue(0);
rotationLoop.current = Animated.loop(
Animated.timing(rotateAnim, {
toValue: 1,
duration: 1000,
easing: Easing.linear,
useNativeDriver: true,
})
);
rotationLoop.current.start();
};
const stopRotation = () => {
rotationLoop.current?.stop();
rotateAnim.setValue(0);
};
const rotate = rotateAnim.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
});
const handlePress = async () => {
if (!isSyncing) {
await onRefresh();
}
};
return (
<TouchableOpacity
onPress={handlePress}
disabled={isSyncing}
style={{
width: size * 2,
height: size + 10,
justifyContent: 'center',
alignItems: 'center'
}}
>
<Animated.View
style={{
transform: [{ rotate }],
width: size,
height: size,
justifyContent: 'center',
alignItems: 'center'
}}
>
<Feather name="refresh-cw" size={size} color={color} />
</Animated.View>
</TouchableOpacity>
);
};
export default RefreshButton;