import { lazy, Suspense, useEffect, useState } from "react"; import type { GraphIssue } from "@understand-anything/core/schema"; import { useDashboardStore } from "../store"; import { useI18n } from "../contexts/I18nContext"; import GraphView from "./GraphView"; import DomainGraphView from "./DomainGraphView"; import KnowledgeGraphView from "./KnowledgeGraphView"; import SearchBar from "./SearchBar"; import NodeInfo from "./NodeInfo"; import ProjectOverview from "./ProjectOverview"; import FileExplorer from "./FileExplorer"; import WarningBanner from "./WarningBanner"; import MobileBottomNav from "./MobileBottomNav"; import type { MobileTab } from "./MobileBottomNav"; import MobileDrawer from "./MobileDrawer"; const CodeViewer = lazy(() => import("./CodeViewer")); const LearnPanel = lazy(() => import("./LearnPanel")); const PathFinderModal = lazy(() => import("./PathFinderModal")); const KeyboardShortcutsHelp = lazy(() => import("./KeyboardShortcutsHelp")); interface Props { accessToken: string; showKeyboardHelp: boolean; setShowKeyboardHelp: (value: boolean) => void; loadError: string | null; allIssues: GraphIssue[]; shortcuts: import("../hooks/useKeyboardShortcuts").KeyboardShortcut[]; } export default function MobileLayout({ accessToken, showKeyboardHelp, setShowKeyboardHelp, loadError, allIssues, shortcuts, }: Props) { const graph = useDashboardStore((s) => s.graph); const selectedNodeId = useDashboardStore((s) => s.selectedNodeId); const tourActive = useDashboardStore((s) => s.tourActive); const persona = useDashboardStore((s) => s.persona); const viewMode = useDashboardStore((s) => s.viewMode); const domainGraph = useDashboardStore((s) => s.domainGraph); const codeViewerOpen = useDashboardStore((s) => s.codeViewerOpen); const closeCodeViewer = useDashboardStore((s) => s.closeCodeViewer); const pathFinderOpen = useDashboardStore((s) => s.pathFinderOpen); const togglePathFinder = useDashboardStore((s) => s.togglePathFinder); const { t } = useI18n(); const [activeTab, setActiveTab] = useState("graph"); const [drawerOpen, setDrawerOpen] = useState(false); const [searchOpen, setSearchOpen] = useState(false); // Auto-pivot to Info when a node is selected — keeps feedback visible // on a small screen where graph and sidebar can't coexist useEffect(() => { if (selectedNodeId) setActiveTab("info"); }, [selectedNodeId]); // When a code viewer opens (e.g. from the Files tab) keep focus there useEffect(() => { if (codeViewerOpen) setSearchOpen(false); }, [codeViewerOpen]); const isLearnMode = tourActive || persona === "junior"; const infoContent = ( <> {selectedNodeId && } {isLearnMode && ( )} {!selectedNodeId && !isLearnMode && } ); return (
{/* Top bar */}

{graph?.project.name ?? t.common.appName}

{/* Search (collapsible) */} {searchOpen && } {/* Validation warnings */} {allIssues.length > 0 && !loadError && } {/* Load error */} {loadError && (
{loadError}
)} {/* Tabbed content — all panes stay mounted to preserve layout/state. Inactive panes are kept in the layout (not display:none) so that ReactFlow keeps real dimensions and pinch/pan don't collapse on tab switch. */}
{viewMode === "knowledge" ? ( ) : viewMode === "domain" && domainGraph ? ( ) : ( )}
{infoContent}
{/* Bottom tab nav */} {/* Drawer */} setDrawerOpen(false)} onTogglePathFinder={togglePathFinder} onShowKeyboardHelp={() => setShowKeyboardHelp(true)} /> {/* Code viewer — always fullscreen on mobile */} {codeViewerOpen && (
event.stopPropagation()} >
)} {/* Keyboard help (mobile reads it as a quick reference too) */} {showKeyboardHelp && ( setShowKeyboardHelp(false)} /> )} {/* Path finder */} {pathFinderOpen && ( )}
); }