import React from 'react'; import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { BLEConnectionState } from '@/services/ble/types'; import { AppColors, BorderRadius, FontSizes, FontWeights, Spacing, } from '@/constants/theme'; interface ConnectionStatusIndicatorProps { connectionState: BLEConnectionState; isReconnecting?: boolean; reconnectAttempts?: number; maxAttempts?: number; onReconnect?: () => void; onCancel?: () => void; compact?: boolean; } /** * Visual indicator for BLE connection status with reconnect controls */ export function ConnectionStatusIndicator({ connectionState, isReconnecting = false, reconnectAttempts = 0, maxAttempts = 3, onReconnect, onCancel, compact = false, }: ConnectionStatusIndicatorProps) { const getStatusConfig = () => { if (isReconnecting) { return { icon: 'sync' as const, color: AppColors.warning, bgColor: AppColors.warningLight, label: `Reconnecting... (${reconnectAttempts}/${maxAttempts})`, showSpinner: true, }; } switch (connectionState) { case BLEConnectionState.READY: return { icon: 'bluetooth' as const, color: AppColors.success, bgColor: AppColors.successLight, label: 'Connected', showSpinner: false, }; case BLEConnectionState.CONNECTING: case BLEConnectionState.DISCOVERING: return { icon: 'bluetooth' as const, color: AppColors.primary, bgColor: AppColors.primaryLighter, label: 'Connecting...', showSpinner: true, }; case BLEConnectionState.DISCONNECTING: return { icon: 'bluetooth' as const, color: AppColors.textMuted, bgColor: AppColors.background, label: 'Disconnecting...', showSpinner: true, }; case BLEConnectionState.ERROR: return { icon: 'warning' as const, color: AppColors.error, bgColor: AppColors.errorLight, label: 'Connection Error', showSpinner: false, }; case BLEConnectionState.DISCONNECTED: default: return { icon: 'bluetooth-outline' as const, color: AppColors.textMuted, bgColor: AppColors.background, label: 'Not Connected', showSpinner: false, }; } }; const config = getStatusConfig(); if (compact) { return ( {config.showSpinner ? ( ) : ( )} {config.label} ); } return ( {config.showSpinner ? ( ) : ( )} {config.label} {isReconnecting && ( Attempting to restore connection... )} {/* Action buttons */} {(connectionState === BLEConnectionState.ERROR || connectionState === BLEConnectionState.DISCONNECTED) && !isReconnecting && onReconnect && ( Reconnect )} {isReconnecting && onCancel && ( Cancel )} ); } const styles = StyleSheet.create({ container: { borderRadius: BorderRadius.lg, padding: Spacing.md, }, compactContainer: { flexDirection: 'row', alignItems: 'center', gap: Spacing.xs, paddingHorizontal: Spacing.sm, paddingVertical: Spacing.xs, borderRadius: BorderRadius.md, }, compactLabel: { fontSize: FontSizes.xs, fontWeight: FontWeights.medium, }, statusRow: { flexDirection: 'row', alignItems: 'center', gap: Spacing.md, }, iconContainer: { width: 32, height: 32, justifyContent: 'center', alignItems: 'center', }, textContainer: { flex: 1, }, label: { fontSize: FontSizes.base, fontWeight: FontWeights.semibold, }, sublabel: { fontSize: FontSizes.sm, color: AppColors.textMuted, marginTop: 2, }, actionButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: Spacing.xs, marginTop: Spacing.md, paddingVertical: Spacing.sm, paddingHorizontal: Spacing.md, borderRadius: BorderRadius.md, borderWidth: 1, borderColor: AppColors.primary, }, actionButtonText: { fontSize: FontSizes.sm, fontWeight: FontWeights.medium, color: AppColors.primary, }, cancelButton: { borderColor: AppColors.error, }, cancelButtonText: { color: AppColors.error, }, }); export default ConnectionStatusIndicator;