Keep the animated ring phase-locked across hosts and derive its knockout surface from each host's actual interaction state. Align filled status circles at 6px while preserving the larger needs-input alert. Co-authored-by: Christoph Leiter <christoph@leiter.io>
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
import { memo } from "react";
|
|
import { View } from "react-native";
|
|
import Animated, { useAnimatedStyle } from "react-native-reanimated";
|
|
import {
|
|
StatusRingFrame,
|
|
type StatusRingProps,
|
|
rotatorStyles,
|
|
styles,
|
|
} from "@/components/status-ring/frame";
|
|
import { useStatusRingRotation } from "@/components/status-ring/clock";
|
|
|
|
/**
|
|
* Native running indicator. The rotation is published by one shared UI-thread clock rather than
|
|
* per-instance timing, so a ring that mounts mid-flight is already in phase — see `clock.ts`.
|
|
*
|
|
* The rotated view carries no theme-tracked style; the coloured arc is nested inside it. Putting
|
|
* a Unistyles style on a Reanimated view crashes on theme change (docs/unistyles.md).
|
|
*/
|
|
export const StatusRing = memo(function StatusRing({ backdrop }: StatusRingProps) {
|
|
const rotation = useStatusRingRotation();
|
|
const rotatorStyle = useAnimatedStyle(() => ({
|
|
transform: [{ rotate: `${rotation.value}deg` }],
|
|
}));
|
|
|
|
return (
|
|
<StatusRingFrame backdrop={backdrop}>
|
|
<Animated.View style={[rotatorStyles.rotator, rotatorStyle]}>
|
|
<View style={styles.arc} />
|
|
</Animated.View>
|
|
</StatusRingFrame>
|
|
);
|
|
});
|