Files
native-app/apps/expo/src/components/player/StatusCircle.tsx
2024-03-06 15:23:43 +01:00

81 lines
1.9 KiB
TypeScript

import React from "react";
import { StyleSheet, View } from "react-native";
import Animated, {
Easing,
useAnimatedProps,
useSharedValue,
withTiming,
} from "react-native-reanimated";
import { Circle, Svg } from "react-native-svg";
import { AntDesign } from "@expo/vector-icons";
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
export const StatusCircle = ({
type,
percentage = 0,
}: {
type: string;
percentage: number;
}) => {
const radius = 25;
const strokeWidth = 5;
const circleCircumference = 2 * Math.PI * radius;
const strokeDashoffset = useSharedValue(circleCircumference);
React.useEffect(() => {
strokeDashoffset.value = withTiming(
circleCircumference - (circleCircumference * percentage) / 100,
{
duration: 500,
easing: Easing.linear,
},
);
}, [circleCircumference, percentage, strokeDashoffset]);
const animatedProps = useAnimatedProps(() => ({
strokeDashoffset: strokeDashoffset.value,
}));
const renderIcon = () => {
switch (type) {
case "success":
return <AntDesign name="checkcircle" size={50} color="green" />;
case "error":
return <AntDesign name="closecircle" size={50} color="red" />;
default:
return null;
}
};
return (
<View style={styles.container}>
<Svg height="60" width="60" viewBox="0 0 60 60">
{type === "loading" && (
<AnimatedCircle
cx="30"
cy="30"
r={radius}
stroke="blue"
strokeWidth={strokeWidth}
fill="none"
strokeDasharray={circleCircumference}
animatedProps={animatedProps}
strokeLinecap="round"
/>
)}
</Svg>
{renderIcon()}
</View>
);
};
const styles = StyleSheet.create({
container: {
justifyContent: "center",
alignItems: "center",
position: "relative",
},
});