mirror of
https://github.com/urosran/cally.git
synced 2025-07-10 15:17:17 +00:00
84 lines
2.0 KiB
TypeScript
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; |