Add reusable WiFiSignalIndicator component with visual bars showing signal strength levels (excellent/good/fair/weak) based on RSSI values. Includes helper functions for signal labels and colors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
102 lines
2.5 KiB
TypeScript
102 lines
2.5 KiB
TypeScript
import React from 'react';
|
|
import { View, StyleSheet } from 'react-native';
|
|
import { AppColors } from '@/constants/theme';
|
|
|
|
export type SignalStrength = 'excellent' | 'good' | 'fair' | 'weak';
|
|
|
|
interface WiFiSignalIndicatorProps {
|
|
rssi: number;
|
|
size?: 'small' | 'medium' | 'large';
|
|
}
|
|
|
|
/**
|
|
* Visual WiFi signal strength indicator with bars
|
|
*
|
|
* RSSI ranges:
|
|
* - Excellent: >= -50 dBm (4 bars)
|
|
* - Good: >= -60 dBm (3 bars)
|
|
* - Fair: >= -70 dBm (2 bars)
|
|
* - Weak: < -70 dBm (1 bar)
|
|
*/
|
|
export function WiFiSignalIndicator({ rssi, size = 'medium' }: WiFiSignalIndicatorProps) {
|
|
const getSignalColor = (rssi: number): string => {
|
|
if (rssi >= -50) return AppColors.success;
|
|
if (rssi >= -60) return AppColors.info;
|
|
if (rssi >= -70) return AppColors.warning;
|
|
return AppColors.error;
|
|
};
|
|
|
|
const getBars = (rssi: number): number => {
|
|
if (rssi >= -50) return 4;
|
|
if (rssi >= -60) return 3;
|
|
if (rssi >= -70) return 2;
|
|
return 1;
|
|
};
|
|
|
|
const color = getSignalColor(rssi);
|
|
const activeBars = getBars(rssi);
|
|
|
|
const sizeStyles = {
|
|
small: { width: 2, maxHeight: 12, gap: 2 },
|
|
medium: { width: 3, maxHeight: 16, gap: 3 },
|
|
large: { width: 4, maxHeight: 20, gap: 4 },
|
|
};
|
|
|
|
const { width: barWidth, maxHeight, gap } = sizeStyles[size];
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
{[1, 2, 3, 4].map((barNumber) => {
|
|
const isActive = barNumber <= activeBars;
|
|
const barHeight = (maxHeight / 4) * barNumber;
|
|
|
|
return (
|
|
<View
|
|
key={barNumber}
|
|
style={[
|
|
styles.bar,
|
|
{
|
|
width: barWidth,
|
|
height: barHeight,
|
|
backgroundColor: isActive ? color : AppColors.border,
|
|
marginLeft: barNumber === 1 ? 0 : gap,
|
|
},
|
|
]}
|
|
/>
|
|
);
|
|
})}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flexDirection: 'row',
|
|
alignItems: 'flex-end',
|
|
justifyContent: 'center',
|
|
},
|
|
bar: {
|
|
borderRadius: 1,
|
|
},
|
|
});
|
|
|
|
/**
|
|
* Get human-readable signal strength label
|
|
*/
|
|
export function getSignalStrengthLabel(rssi: number): string {
|
|
if (rssi >= -50) return 'Excellent';
|
|
if (rssi >= -60) return 'Good';
|
|
if (rssi >= -70) return 'Fair';
|
|
return 'Weak';
|
|
}
|
|
|
|
/**
|
|
* Get signal strength color
|
|
*/
|
|
export function getSignalStrengthColor(rssi: number): string {
|
|
if (rssi >= -50) return AppColors.success;
|
|
if (rssi >= -60) return AppColors.info;
|
|
if (rssi >= -70) return AppColors.warning;
|
|
return AppColors.error;
|
|
}
|