import { useEffect, useState } from 'react'; import { BrowserRouter, Routes, Route, useParams } from 'react-router-dom'; import { api } from '@/api/client'; import { ProjectSidebar } from '@/components/ProjectSidebar'; import { RightRail } from '@/components/RightRail'; import { Home } from '@/pages/Home'; import { Project } from '@/pages/Project'; import { Session } from '@/pages/Session'; import { Settings } from '@/pages/Settings'; import { Toaster } from '@/components/ui/sonner'; import { useUserEvents } from '@/hooks/useUserEvents'; import { useTheme } from '@/lib/theme'; import { SidebarDrawerProvider, useSidebarDrawer } from '@/hooks/useSidebarDrawer'; import { RightRailDrawerProvider, useRightRailDrawer } from '@/hooks/useRightRailDrawer'; import { useViewport } from '@/hooks/useViewport'; function SessionRightRail() { const { id } = useParams<{ id: string }>(); if (!id) return null; return ; } function RightRailForSession({ sessionId }: { sessionId: string }) { const [projectId, setProjectId] = useState(null); useEffect(() => { api.sessions .get(sessionId) .then((s) => setProjectId(s.project_id)) .catch((err) => console.warn('RightRail: failed to fetch session', err)); }, [sessionId]); if (!projectId) return null; // v1.6.2: rendered on all viewports. On mobile, RightRail itself renders as // a right-side drawer toggled by the header's FolderTree button (via // useRightRailDrawer). On desktop, it renders inline as before with its // own internal open/close state. return ; } function MobileBackdrop() { const { open, setOpen } = useSidebarDrawer(); const { isMobile } = useViewport(); if (!isMobile || !open) return null; return (
setOpen(false)} aria-hidden="true" /> ); } function MobileRightRailBackdrop() { const { open, setOpen } = useRightRailDrawer(); const { isMobile } = useViewport(); if (!isMobile || !open) return null; return (
setOpen(false)} aria-hidden="true" /> ); } function AppShell() { // themes-v1: useTheme() owns the matchMedia subscription for system mode // and reconciles cache with /api/settings on mount. Mounted first so the // theme class on is correct before any child renders. useTheme(); useUserEvents(); // v1.10.8c: h-dvh (dynamic viewport) instead of h-screen (100vh) so the // root height excludes the iOS URL-bar overlay area. Without this, every // descendant — including the terminal pane — measures itself against a // height that extends behind the URL bar, and xterm allocates extra rows // that scroll out of reach on iPhone. return (
} /> } /> } /> } />
} />
); } export default function App() { return ( ); }