mirror of
https://github.com/ruvnet/RuView
synced 2026-08-06 19:51:43 +00:00
feat: Implement RSSI service for iOS and Web platforms
- Added IosRssiService to handle synthetic RSSI data for iOS. - Created WebRssiService to simulate RSSI scanning on the web. - Defined shared types for WifiNetwork and RssiService in rssi.service.ts. - Introduced simulation service to generate synthetic sensing data. - Implemented WebSocket service for real-time data handling with reconnection logic. - Established Zustand stores for managing application state related to MAT and pose data. - Developed theme context and utility functions for consistent styling and formatting. - Added type definitions for various application entities including API responses and sensing data. - Created utility functions for color mapping and URL validation. - Configured TypeScript settings for the mobile application.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { useEffect } from 'react';
|
||||
import { StyleSheet, ViewStyle } from 'react-native';
|
||||
import Animated, {
|
||||
cancelAnimation,
|
||||
Easing,
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withRepeat,
|
||||
withSequence,
|
||||
withTiming,
|
||||
} from 'react-native-reanimated';
|
||||
import { colors } from '../theme/colors';
|
||||
|
||||
type StatusType = 'connected' | 'simulated' | 'disconnected' | 'connecting';
|
||||
|
||||
type StatusDotProps = {
|
||||
status: StatusType;
|
||||
size?: number;
|
||||
style?: ViewStyle;
|
||||
};
|
||||
|
||||
const resolveColor = (status: StatusType): string => {
|
||||
if (status === 'connecting') return colors.warn;
|
||||
return colors[status];
|
||||
};
|
||||
|
||||
export const StatusDot = ({ status, size = 10, style }: StatusDotProps) => {
|
||||
const scale = useSharedValue(1);
|
||||
const opacity = useSharedValue(1);
|
||||
const isConnecting = status === 'connecting';
|
||||
|
||||
useEffect(() => {
|
||||
if (isConnecting) {
|
||||
scale.value = withRepeat(
|
||||
withSequence(
|
||||
withTiming(1.35, { duration: 800, easing: Easing.out(Easing.cubic) }),
|
||||
withTiming(1, { duration: 800, easing: Easing.in(Easing.cubic) }),
|
||||
),
|
||||
-1,
|
||||
);
|
||||
opacity.value = withRepeat(
|
||||
withSequence(
|
||||
withTiming(0.4, { duration: 800, easing: Easing.out(Easing.quad) }),
|
||||
withTiming(1, { duration: 800, easing: Easing.in(Easing.quad) }),
|
||||
),
|
||||
-1,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
cancelAnimation(scale);
|
||||
cancelAnimation(opacity);
|
||||
scale.value = 1;
|
||||
opacity.value = 1;
|
||||
}, [isConnecting, opacity, scale]);
|
||||
|
||||
const animatedStyle = useAnimatedStyle(() => ({
|
||||
transform: [{ scale: scale.value }],
|
||||
opacity: opacity.value,
|
||||
}));
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.dot,
|
||||
{
|
||||
width: size,
|
||||
height: size,
|
||||
backgroundColor: resolveColor(status),
|
||||
borderRadius: size / 2,
|
||||
},
|
||||
animatedStyle,
|
||||
style,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
dot: {
|
||||
borderRadius: 999,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user