diff --git a/packages/app/src/app/_layout.tsx b/packages/app/src/app/_layout.tsx index 2e7b449c1..982cc17af 100644 --- a/packages/app/src/app/_layout.tsx +++ b/packages/app/src/app/_layout.tsx @@ -7,6 +7,7 @@ import { SessionProvider } from "@/contexts/session-context"; import { RealtimeProvider } from "@/contexts/realtime-context"; import { useSettings } from "@/hooks/use-settings"; import { View, ActivityIndicator } from "react-native"; +import { GlobalFooter } from "@/components/global-footer"; function ProvidersWrapper({ children }: { children: React.ReactNode }) { const { settings, isLoading } = useSettings(); @@ -40,23 +41,26 @@ export default function RootLayout() { - - - - - - - + + + + + + + + + + diff --git a/packages/app/src/app/agent/[id].tsx b/packages/app/src/app/agent/[id].tsx index 4776a0634..7d26106be 100644 --- a/packages/app/src/app/agent/[id].tsx +++ b/packages/app/src/app/agent/[id].tsx @@ -6,7 +6,7 @@ import ReanimatedAnimated, { useAnimatedStyle } from "react-native-reanimated"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { BackHeader } from "@/components/headers/back-header"; import { AgentStreamView } from "@/components/agent-stream-view"; -import { GlobalFooter } from "@/components/global-footer"; +import { AgentInputArea } from "@/components/agent-input-area"; import { useSession } from "@/contexts/session-context"; export default function AgentScreen() { @@ -60,8 +60,10 @@ export default function AgentScreen() { } /> - {/* Footer */} - + {/* Agent Input - will hide itself when realtime is active */} + + + ); @@ -75,6 +77,11 @@ const styles = StyleSheet.create((theme) => ({ content: { flex: 1, }, + inputContainer: { + backgroundColor: theme.colors.background, + borderTopWidth: theme.borderWidth[1], + borderTopColor: theme.colors.border, + }, errorContainer: { flex: 1, alignItems: "center", diff --git a/packages/app/src/app/index.tsx b/packages/app/src/app/index.tsx index cc09fa8d7..30e393f03 100644 --- a/packages/app/src/app/index.tsx +++ b/packages/app/src/app/index.tsx @@ -7,7 +7,6 @@ import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { HomeHeader } from "@/components/headers/home-header"; import { EmptyState } from "@/components/empty-state"; import { AgentList } from "@/components/agent-list"; -import { GlobalFooter } from "@/components/global-footer"; import { CreateAgentModal } from "@/components/create-agent-modal"; import { useSession } from "@/contexts/session-context"; @@ -46,9 +45,6 @@ export default function HomeScreen() { ) : ( )} - - {/* Footer */} - {/* Create Agent Modal */} diff --git a/packages/app/src/app/orchestrator.tsx b/packages/app/src/app/orchestrator.tsx index e9665339c..bb54d8857 100644 --- a/packages/app/src/app/orchestrator.tsx +++ b/packages/app/src/app/orchestrator.tsx @@ -6,7 +6,6 @@ import ReanimatedAnimated, { useAnimatedStyle } from "react-native-reanimated"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { BackHeader } from "@/components/headers/back-header"; import { OrchestratorMessagesView } from "@/components/orchestrator-messages-view"; -import { GlobalFooter } from "@/components/global-footer"; import { useSession } from "@/contexts/session-context"; import type { ScrollView } from "react-native"; import type { Artifact } from "@/components/artifact-drawer"; @@ -47,9 +46,6 @@ export default function OrchestratorScreen() { currentAssistantMessage={currentAssistantMessage} onArtifactClick={handleArtifactClick} /> - - {/* Footer */} - ); diff --git a/packages/app/src/components/agent-input-area.tsx b/packages/app/src/components/agent-input-area.tsx index 6c1804d67..bf07025fc 100644 --- a/packages/app/src/components/agent-input-area.tsx +++ b/packages/app/src/components/agent-input-area.tsx @@ -14,7 +14,7 @@ interface AgentInputAreaProps { export function AgentInputArea({ agentId }: AgentInputAreaProps) { const { theme } = useUnistyles(); const { agents, ws, sendAgentMessage, setAgentMode } = useSession(); - const { startRealtime } = useRealtime(); + const { isRealtimeMode, startRealtime } = useRealtime(); const audioRecorder = useAudioRecorder(); const [userInput, setUserInput] = useState(""); @@ -24,6 +24,11 @@ export function AgentInputArea({ agentId }: AgentInputAreaProps) { const agent = agents.get(agentId); + // Hide when realtime is active - global footer takes over + if (isRealtimeMode) { + return null; + } + async function handleSendMessage() { if (!userInput.trim() || !ws.isConnected) return; diff --git a/packages/app/src/components/global-footer.tsx b/packages/app/src/components/global-footer.tsx index c7168faf7..9b158513c 100644 --- a/packages/app/src/components/global-footer.tsx +++ b/packages/app/src/components/global-footer.tsx @@ -1,21 +1,17 @@ import { View, Pressable } from "react-native"; -import { usePathname } from "expo-router"; +import { usePathname, useLocalSearchParams } from "expo-router"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { AudioLines } from "lucide-react-native"; import { useRealtime } from "@/contexts/realtime-context"; import { useSession } from "@/contexts/session-context"; import { RealtimeControls } from "./realtime-controls"; -import { AgentInputArea } from "./agent-input-area"; -interface GlobalFooterProps { - agentId?: string; -} - -export function GlobalFooter({ agentId }: GlobalFooterProps) { +export function GlobalFooter() { const { theme } = useUnistyles(); const insets = useSafeAreaInsets(); const pathname = usePathname(); + const params = useLocalSearchParams(); const { isRealtimeMode, startRealtime } = useRealtime(); const { ws } = useSession(); @@ -33,13 +29,9 @@ export function GlobalFooter({ agentId }: GlobalFooterProps) { ); } - // If on agent screen, show full input area - if (isAgentScreen && agentId) { - return ( - - - - ); + // If on agent screen and realtime is off, hide footer (agent has its own controls) + if (isAgentScreen) { + return null; } // For home and orchestrator screens, show centered realtime button