diff --git a/packages/app/src/app/_layout.tsx b/packages/app/src/app/_layout.tsx index 88efbfeeb..a166c880a 100644 --- a/packages/app/src/app/_layout.tsx +++ b/packages/app/src/app/_layout.tsx @@ -1,4 +1,4 @@ -import { Stack, useLocalSearchParams, usePathname } from "expo-router"; +import { Stack, usePathname } from "expo-router"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { KeyboardProvider } from "react-native-keyboard-controller"; import { GestureHandlerRootView } from "react-native-gesture-handler"; @@ -72,17 +72,21 @@ function ProvidersWrapper({ children }: { children: ReactNode }) { function AppWithSidebar({ children }: { children: ReactNode }) { const pathname = usePathname(); - const params = useLocalSearchParams<{ agentId?: string }>(); - const selectedAgentId = useMemo(() => { - if (pathname.startsWith("/agent/") && params.agentId) { - return params.agentId; + // Parse selectedAgentKey directly from pathname + // useLocalSearchParams doesn't update when navigating between same-pattern routes + const selectedAgentKey = useMemo(() => { + // Match /agent/[serverId]/[agentId] pattern + const match = pathname.match(/^\/agent\/([^/]+)\/([^/]+)$/); + if (match) { + const [, serverId, agentId] = match; + return `${serverId}:${agentId}`; } return undefined; - }, [pathname, params.agentId]); + }, [pathname]); return ( - {children} + {children} ); } diff --git a/packages/app/src/app/settings.tsx b/packages/app/src/app/settings.tsx index 25403029c..892cac23d 100644 --- a/packages/app/src/app/settings.tsx +++ b/packages/app/src/app/settings.tsx @@ -18,7 +18,7 @@ import { useDaemonRegistry, type DaemonProfile } from "@/contexts/daemon-registr import { useDaemonConnections, type ConnectionStatus } from "@/contexts/daemon-connections-context"; import { formatConnectionStatus, getConnectionStatusTone } from "@/utils/daemons"; import { theme as defaultTheme } from "@/styles/theme"; -import { BackHeader } from "@/components/headers/back-header"; +import { MenuHeader } from "@/components/headers/menu-header"; import { useSessionStore } from "@/stores/session-store"; import type { UseWebSocketReturn } from "@/hooks/use-websocket"; @@ -575,7 +575,7 @@ export default function SettingsScreen() { return ( - + diff --git a/packages/app/src/components/agent-list.tsx b/packages/app/src/components/agent-list.tsx index 5fdd1ba03..f0035d8d8 100644 --- a/packages/app/src/components/agent-list.tsx +++ b/packages/app/src/components/agent-list.tsx @@ -57,9 +57,12 @@ export function AgentList({ agents, isRefreshing = false, onRefresh, selectedAge to: "agent", params: { serverId, agentId }, }); + const shouldReplace = pathname.startsWith("/agent/"); const navigate = shouldReplace ? router.replace : router.push; + onAgentSelect?.(); + navigate({ pathname: "/agent/[serverId]/[agentId]", params: { @@ -91,7 +94,8 @@ export function AgentList({ agents, isRefreshing = false, onRefresh, selectedAge ({ item: agent }) => { const timeAgo = formatTimeAgo(agent.lastActivityAt); const isRunning = agent.status === "running"; - const isSelected = selectedAgentId === agent.id; + const agentKey = `${agent.serverId}:${agent.id}`; + const isSelected = selectedAgentId === agentKey; const statusColor = isRunning ? "#3b82f6" : agent.requiresAttention ? "#22c55e" : null; return ( @@ -225,7 +229,6 @@ const styles = StyleSheet.create((theme) => ({ paddingHorizontal: theme.spacing[3], borderRadius: theme.borderRadius.lg, marginBottom: theme.spacing[2], - backgroundColor: theme.colors.palette.zinc[950], }, agentItemSelected: { backgroundColor: theme.colors.palette.zinc[800], diff --git a/packages/app/src/components/sliding-sidebar.tsx b/packages/app/src/components/sliding-sidebar.tsx index 61c0fc12f..7960af9bd 100644 --- a/packages/app/src/components/sliding-sidebar.tsx +++ b/packages/app/src/components/sliding-sidebar.tsx @@ -234,17 +234,12 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) { + {/* Header: New Agent button */} - - - + + {/* Middle: scrollable agent list */} + + {/* Footer: Settings button */} + + + + Settings + + @@ -283,10 +291,8 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) { return ( + {/* Header: New Agent button */} - - - + + {/* Middle: scrollable agent list */} + + {/* Footer: Settings button */} + + + + Settings + + ); } @@ -336,19 +355,11 @@ const styles = StyleSheet.create((theme) => ({ backgroundColor: theme.colors.background, }, sidebarHeader: { - flexDirection: "row", - alignItems: "center", paddingHorizontal: theme.spacing[4], paddingTop: theme.spacing[4], paddingBottom: theme.spacing[2], - gap: theme.spacing[2], - }, - headerIconButton: { - padding: theme.spacing[2], - borderRadius: theme.borderRadius.lg, }, newAgentButton: { - flex: 1, flexDirection: "row", alignItems: "center", justifyContent: "center", @@ -360,4 +371,23 @@ const styles = StyleSheet.create((theme) => ({ fontSize: theme.fontSize.base, fontWeight: theme.fontWeight.normal, }, + sidebarFooter: { + paddingHorizontal: theme.spacing[4], + paddingTop: theme.spacing[2], + paddingBottom: theme.spacing[4], + borderTopWidth: 1, + borderTopColor: theme.colors.border, + }, + settingsButton: { + flexDirection: "row", + alignItems: "center", + gap: theme.spacing[3], + paddingVertical: theme.spacing[2], + paddingHorizontal: theme.spacing[2], + }, + settingsButtonText: { + fontSize: theme.fontSize.base, + fontWeight: theme.fontWeight.normal, + color: theme.colors.mutedForeground, + }, }));