import {
AgentSidebar,
focusAgentChat,
isAgentChatHomeHandoffActive,
navigateWithAgentChatViewTransition,
useAgentChatHomeHandoff,
useAgentChatHomeHandoffLinks,
} from "@agent-native/core/client/agent-chat";
import { getBrowserTabId } from "@agent-native/core/client/hooks";
import { isEmbedAuthActive } from "@agent-native/core/client/host";
import { useT } from "@agent-native/core/client/i18n";
import { InvitationBanner } from "@agent-native/core/client/org";
import {
EMBED_MODE_QUERY_PARAM,
EMBED_TOKEN_QUERY_PARAM,
} from "@agent-native/core/shared";
import { CreativeContextComposerChip } from "@agent-native/creative-context/client";
import { HeaderActionsProvider } from "@agent-native/toolkit/app-shell";
import { IconMenu2 } from "@tabler/icons-react";
import { useState, useEffect } from "react";
import { useLocation, useNavigate } from "react-router";
import { GenerationResults } from "@/components/generation/GenerationResults";
import { useImageModelMenu } from "@/hooks/use-image-model-menu";
import { useNavigationState } from "@/hooks/use-navigation-state";
import { ASSETS_CHAT_STORAGE_KEY } from "@/lib/chat";
import { cn } from "@/lib/utils";
import { Header } from "./Header";
import { Sidebar } from "./Sidebar";
interface LayoutProps {
children: React.ReactNode;
}
function isEmbeddedWindow() {
if (typeof window === "undefined") return false;
try {
return window.self !== window.top;
} catch {
return true;
}
}
function searchParamsEnableEmbeddedMode(search: string): boolean {
const params = new URLSearchParams(search);
const embedMode = params.get(EMBED_MODE_QUERY_PARAM);
return (
params.has(EMBED_TOKEN_QUERY_PARAM) ||
embedMode === "1" ||
embedMode === "true"
);
}
export function Layout({ children }: LayoutProps) {
useNavigationState();
const location = useLocation();
const navigate = useNavigate();
const t = useT();
const imageModelMenu = useImageModelMenu();
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
const isCreateRoute =
location.pathname === "/" || location.pathname.startsWith("/chat/");
const chatHomeHandoffActive = useAgentChatHomeHandoff({
storageKey: ASSETS_CHAT_STORAGE_KEY,
activePath: location.pathname,
enabled: !isCreateRoute,
});
const chatHomeHandoffPending = isAgentChatHomeHandoffActive(
ASSETS_CHAT_STORAGE_KEY,
);
useAgentChatHomeHandoffLinks({
storageKey: ASSETS_CHAT_STORAGE_KEY,
isChatPath: (pathname) => pathname === "/" || pathname.startsWith("/chat/"),
// Only preserve the transition when chat activity has recorded an active
// handoff; an empty home chat should keep the destination sidebar closed.
requireActiveHandoff: true,
});
useEffect(() => {
setMobileSidebarOpen(false);
}, [location.pathname]);
const isPicker = location.pathname === "/library";
const hideHeader =
location.pathname === "/library" ||
location.pathname.startsWith("/library/") ||
location.pathname === "/extensions" ||
location.pathname.startsWith("/extensions/");
const chromeless =
(isPicker &&
(searchParamsEnableEmbeddedMode(location.search) ||
isEmbeddedWindow() ||
isEmbedAuthActive())) ||
location.pathname.endsWith("/embed");
if (chromeless) {
return (