import { useDisclosure } from "@nextui-org/react"; import React from "react"; import { Outlet } from "react-router"; import { useDispatch } from "react-redux"; import { FaServer } from "react-icons/fa"; import toast from "react-hot-toast"; import { useTranslation } from "react-i18next"; import { I18nKey } from "#/i18n/declaration"; import { ConversationProvider, useConversation, } from "#/context/conversation-context"; import { Controls } from "#/components/features/controls/controls"; import { clearMessages } from "#/state/chat-slice"; import { clearTerminal } from "#/state/command-slice"; import { useEffectOnce } from "#/hooks/use-effect-once"; import CodeIcon from "#/icons/code.svg?react"; import GlobeIcon from "#/icons/globe.svg?react"; import ListIcon from "#/icons/list-type-number.svg?react"; import { clearJupyter } from "#/state/jupyter-slice"; import { FilesProvider } from "#/context/files"; import { ChatInterface } from "../../components/features/chat/chat-interface"; import { WsClientProvider } from "#/context/ws-client-provider"; import { EventHandler } from "./event-handler"; import { useAuth } from "#/context/auth-context"; import { useConversationConfig } from "#/hooks/query/use-conversation-config"; import { Container } from "#/components/layout/container"; import { Orientation, ResizablePanel, } from "#/components/layout/resizable-panel"; import Security from "#/components/shared/modals/security/security"; import { useEndSession } from "#/hooks/use-end-session"; import { useUserConversation } from "#/hooks/query/use-user-conversation"; import { ServedAppLabel } from "#/components/layout/served-app-label"; import { TerminalStatusLabel } from "#/components/features/terminal/terminal-status-label"; import { useSettings } from "#/hooks/query/use-settings"; import { MULTI_CONVERSATION_UI } from "#/utils/feature-flags"; function AppContent() { useConversationConfig(); const { t } = useTranslation(); const { gitHubToken } = useAuth(); const { data: settings } = useSettings(); const { conversationId } = useConversation(); const { data: conversation, isFetched } = useUserConversation( conversationId || null, ); const dispatch = useDispatch(); const endSession = useEndSession(); const [width, setWidth] = React.useState(window.innerWidth); const secrets = React.useMemo( () => [gitHubToken].filter((secret) => secret !== null), [gitHubToken], ); const Terminal = React.useMemo( () => React.lazy(() => import("#/components/features/terminal/terminal")), [], ); React.useEffect(() => { if (MULTI_CONVERSATION_UI && isFetched && !conversation) { toast.error( "This conversation does not exist, or you do not have permission to access it.", ); endSession(); } }, [conversation, isFetched]); React.useEffect(() => { dispatch(clearMessages()); dispatch(clearTerminal()); dispatch(clearJupyter()); }, [conversationId]); useEffectOnce(() => { dispatch(clearMessages()); dispatch(clearTerminal()); dispatch(clearJupyter()); }); function handleResize() { setWidth(window.innerWidth); } React.useEffect(() => { window.addEventListener("resize", handleResize); return () => { window.removeEventListener("resize", handleResize); }; }, []); const { isOpen: securityModalIsOpen, onOpen: onSecurityModalOpen, onOpenChange: onSecurityModalOpenChange, } = useDisclosure(); function renderMain() { if (width <= 640) { return (