"use client"; import { useEffect, useState } from "react"; import { usePathname, useRouter } from "next/navigation"; import { useQuery } from "@tanstack/react-query"; import { useUI } from "@/lib/client/store"; import { Sidebar } from "./Sidebar"; import { TopBar } from "./TopBar"; import { MobileNav } from "./MobileNav"; import { CommandPalette } from "./CommandPalette"; import { AIPanel } from "./AIPanel"; import { ShortcutsDialog } from "./ShortcutsDialog"; import { Minimize2 } from "lucide-react"; import type { TreeNode, ShellUser } from "./types"; import { cn } from "@/lib/utils"; import { api } from "@/lib/client/api"; import { applyPrefs, readLocalPrefs } from "@/components/settings/prefs"; export function Shell({ user, workspace, initialTree, children }: { user: ShellUser; workspace: { id: string; name: string }; initialTree: TreeNode[]; children: React.ReactNode }) { const ui = useUI(); const r = useRouter(); const pathname = usePathname(); const [help, setHelp] = useState(false); const { data: tree = initialTree } = useQuery({ queryKey: ["tree"], queryFn: () => api("/api/tree"), initialData: initialTree, staleTime: 10_000 }); useEffect(() => { ui.setTheme(ui.theme); try { applyPrefs(readLocalPrefs()); } catch {} /* eslint-disable-next-line */ }, []); useEffect(() => { const onKey = (e: KeyboardEvent) => { const mod = e.metaKey || e.ctrlKey; if (mod && e.key === "k") { e.preventDefault(); ui.set({ paletteOpen: !ui.paletteOpen }); } else if (mod && e.key === "/") { e.preventDefault(); ui.toggleAI(); } else if (mod && e.key === "\\") { e.preventDefault(); ui.toggleSidebar(); } else if (mod && e.shiftKey && e.key.toLowerCase() === "n") { e.preventDefault(); api("/api/pages", { method: "POST", json: { title: "" } }).then((p) => r.push(`/p/${p.id}`)); } else if (mod && e.key === ".") { e.preventDefault(); ui.set({ focusMode: !ui.focusMode }); } else if (mod && (e.key === "?" || (e.shiftKey && e.key === "/"))) { e.preventDefault(); setHelp((h) => !h); } else if (e.key === "Escape" && ui.focusMode && !(e.target as HTMLElement)?.closest?.(".ProseMirror")) ui.set({ focusMode: false }); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [ui, r]); useEffect(() => { if ("serviceWorker" in navigator && process.env.NODE_ENV === "production") navigator.serviceWorker.register("/sw.js").catch(() => {}); }, []); const sidebar = ui.sidebarOpen && !ui.focusMode; return (
{!ui.focusMode && }
{children}
{ui.aiOpen && !ui.focusMode && } {ui.focusMode && }
); }