import { useEffect, useState } from "react"; import { View, Pressable, Text } from "react-native"; import { usePathname, useRouter } from "expo-router"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { AudioLines, Users, Plus } from "lucide-react-native"; import { useRealtime } from "@/contexts/realtime-context"; import { useSession } from "@/contexts/session-context"; import { useFooterControls, FOOTER_HEIGHT } from "@/contexts/footer-controls-context"; import { RealtimeControls } from "./realtime-controls"; import { CreateAgentModal } from "./create-agent-modal"; import Animated, { FadeIn, FadeOut, useAnimatedStyle, withTiming, useSharedValue, } from "react-native-reanimated"; import { useReanimatedKeyboardAnimation } from "react-native-keyboard-controller"; export function GlobalFooter() { const { theme } = useUnistyles(); const insets = useSafeAreaInsets(); const pathname = usePathname(); const router = useRouter(); const { isRealtimeMode, startRealtime } = useRealtime(); const { ws } = useSession(); const { controls } = useFooterControls(); const [showCreateModal, setShowCreateModal] = useState(false); // Determine current screen type const isAgentScreen = pathname?.startsWith("/agent/"); const agentControlsHeight = useSharedValue(FOOTER_HEIGHT); const hasRegisteredControls = !!controls; const showAgentControls = isAgentScreen && hasRegisteredControls; const transition = useSharedValue(isRealtimeMode ? 1 : 0); const { height: keyboardHeight } = useReanimatedKeyboardAnimation(); const bottomInset = insets.bottom; useEffect(() => { if (showAgentControls) { transition.value = withTiming(isRealtimeMode ? 1 : 0, { duration: 250 }); } }, [isRealtimeMode, showAgentControls]); const keyboardAnimatedStyle = useAnimatedStyle( () => { "worklet"; const absoluteHeight = Math.abs(keyboardHeight.value); const shift = Math.max(0, absoluteHeight - bottomInset); return { transform: [{ translateY: -shift }], }; }, [bottomInset], ); const containerAnimatedStyle = useAnimatedStyle( () => { "worklet"; const agentHeight = Math.max(agentControlsHeight.value, FOOTER_HEIGHT); const expandedHeight = agentHeight - (agentHeight - FOOTER_HEIGHT) * transition.value; return { height: expandedHeight + bottomInset, }; }, [bottomInset], ); const realtimeAnimatedStyle = useAnimatedStyle(() => { return { opacity: transition.value, pointerEvents: transition.value > 0.5 ? ("auto" as const) : ("none" as const), }; }); const agentControlsAnimatedStyle = useAnimatedStyle(() => { return { opacity: 1 - transition.value, pointerEvents: transition.value < 0.5 ? ("auto" as const) : ("none" as const), }; }); if (showAgentControls) { return ( { agentControlsHeight.value = Math.max(event.nativeEvent.layout.height, FOOTER_HEIGHT); }} style={[styles.absoluteBottomFill, agentControlsAnimatedStyle]} > {controls} ); } if (isAgentScreen) { return null; } // Determine if realtime is active on non-agent screens if (isRealtimeMode) { return ( ); } // For home and orchestrator screens, show three buttons return ( <> router.push("/")} style={({ pressed }) => [ styles.footerButton, pressed && styles.buttonPressed, ]} > Agents setShowCreateModal(true)} style={({ pressed }) => [ styles.footerButton, pressed && styles.buttonPressed, ]} > New Agent [ styles.footerButton, !ws.isConnected && styles.buttonDisabled, pressed && !ws.isConnected && styles.buttonPressed, ]} > Realtime setShowCreateModal(false)} /> ); } const styles = StyleSheet.create((theme) => ({ container: { backgroundColor: theme.colors.background, borderTopWidth: theme.borderWidth[1], borderTopColor: theme.colors.border, }, content: { flex: 1, minHeight: FOOTER_HEIGHT, }, absoluteBottomFill: { position: "absolute", left: 0, right: 0, bottom: 0, }, threeButtonContainer: { flexDirection: "row", padding: theme.spacing[4], gap: theme.spacing[3], }, footerButton: { flex: 1, flexDirection: "column", alignItems: "center", justifyContent: "center", paddingVertical: theme.spacing[3], gap: theme.spacing[1], }, footerButtonText: { color: theme.colors.foreground, fontSize: theme.fontSize.xs, fontWeight: theme.fontWeight.normal, }, buttonDisabled: { opacity: 0.5, }, buttonPressed: { opacity: 0.5, }, }));