/** * Voice Floating Action Button Component * * A floating action button for initiating voice calls with Julia AI. * Shows on screens where voice chat is available. * Hidden when a call is already active. */ import React, { useRef, useEffect } from 'react'; import { StyleSheet, TouchableOpacity, Animated, ViewStyle, } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { AppColors, BorderRadius } from '@/constants/theme'; import { useVoiceCall } from '@/contexts/VoiceCallContext'; interface VoiceFABProps { onPress: () => void; style?: ViewStyle; disabled?: boolean; } const FAB_SIZE = 56; export function VoiceFAB({ onPress, style, disabled = false }: VoiceFABProps) { const { isCallActive } = useVoiceCall(); const insets = useSafeAreaInsets(); // Animation values const scale = useRef(new Animated.Value(1)).current; const opacity = useRef(new Animated.Value(1)).current; // Hide FAB when call is active useEffect(() => { if (isCallActive) { Animated.parallel([ Animated.timing(scale, { toValue: 0, duration: 200, useNativeDriver: true, }), Animated.timing(opacity, { toValue: 0, duration: 200, useNativeDriver: true, }), ]).start(); } else { Animated.parallel([ Animated.spring(scale, { toValue: 1, friction: 5, tension: 40, useNativeDriver: true, }), Animated.timing(opacity, { toValue: 1, duration: 200, useNativeDriver: true, }), ]).start(); } }, [isCallActive, scale, opacity]); // Press animation const handlePressIn = () => { Animated.spring(scale, { toValue: 0.9, friction: 5, useNativeDriver: true, }).start(); }; const handlePressOut = () => { Animated.spring(scale, { toValue: 1, friction: 5, useNativeDriver: true, }).start(); }; // Don't render if call is active if (isCallActive) { return null; } return ( ); } const styles = StyleSheet.create({ container: { position: 'absolute', right: 16, zIndex: 100, }, fab: { width: FAB_SIZE, height: FAB_SIZE, borderRadius: BorderRadius.full, backgroundColor: AppColors.success, justifyContent: 'center', alignItems: 'center', shadowColor: '#000', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.3, shadowRadius: 8, elevation: 8, }, fabDisabled: { backgroundColor: AppColors.surface, shadowOpacity: 0.1, }, });