import { PanelRightOpen, History, PlusCircle, GitBranch, Info, } from "lucide-react"; import { PanelRightClose } from "lucide-react"; import { useAtom, useAtomValue } from "jotai"; import { selectedAppIdAtom } from "@/atoms/appAtoms"; import { useVersions } from "@/hooks/useVersions"; import { Button } from "../ui/button"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "../ui/tooltip"; import { IpcClient } from "@/ipc/ipc_client"; import { useRouter } from "@tanstack/react-router"; import { selectedChatIdAtom } from "@/atoms/chatAtoms"; import { useChats } from "@/hooks/useChats"; import { showError, showSuccess } from "@/lib/toast"; import { useEffect } from "react"; import { useStreamChat } from "@/hooks/useStreamChat"; import { useCurrentBranch } from "@/hooks/useCurrentBranch"; import { useCheckoutVersion } from "@/hooks/useCheckoutVersion"; import { useRenameBranch } from "@/hooks/useRenameBranch"; import { isAnyCheckoutVersionInProgressAtom } from "@/store/appAtoms"; import { LoadingBar } from "../ui/LoadingBar"; interface ChatHeaderProps { isVersionPaneOpen: boolean; isPreviewOpen: boolean; onTogglePreview: () => void; onVersionClick: () => void; } export function ChatHeader({ isVersionPaneOpen, isPreviewOpen, onTogglePreview, onVersionClick, }: ChatHeaderProps) { const appId = useAtomValue(selectedAppIdAtom); const { versions, loading: versionsLoading } = useVersions(appId); const { navigate } = useRouter(); const [selectedChatId, setSelectedChatId] = useAtom(selectedChatIdAtom); const { refreshChats } = useChats(appId); const { isStreaming } = useStreamChat(); const isAnyCheckoutVersionInProgress = useAtomValue( isAnyCheckoutVersionInProgressAtom, ); const { branchInfo, isLoading: branchInfoLoading, refetchBranchInfo, } = useCurrentBranch(appId); const { checkoutVersion, isCheckingOutVersion } = useCheckoutVersion(); const { renameBranch, isRenamingBranch } = useRenameBranch(); useEffect(() => { if (appId) { refetchBranchInfo(); } }, [appId, selectedChatId, isStreaming, refetchBranchInfo]); const handleCheckoutMainBranch = async () => { if (!appId) return; await checkoutVersion({ appId, versionId: "main" }); }; const handleRenameMasterToMain = async () => { if (!appId) return; // If this throws, it will automatically show an error toast await renameBranch({ oldBranchName: "master", newBranchName: "main" }); showSuccess("Master branch renamed to main"); }; const handleNewChat = async () => { if (appId) { try { const chatId = await IpcClient.getInstance().createChat(appId); setSelectedChatId(chatId); navigate({ to: "/chat", search: { id: chatId }, }); await refreshChats(); } catch (error) { showError(`Failed to create new chat: ${(error as any).toString()}`); } } else { navigate({ to: "/" }); } }; // REMINDER: KEEP UP TO DATE WITH app_handlers.ts const versionPostfix = versions.length === 100_000 ? `+` : ""; const isNotMainBranch = branchInfo && branchInfo.branch !== "main"; const currentBranchName = branchInfo?.branch; return (
{/* If the version pane is open, it's expected to not always be on the main branch. */} {isNotMainBranch && !isVersionPaneOpen && (
{currentBranchName === "" && ( <> {isAnyCheckoutVersionInProgress ? ( <> Please wait, switching back to latest version... ) : ( <> Warning: You are not on a branch )}

{isAnyCheckoutVersionInProgress ? "Version checkout is currently in progress" : "Checkout main branch, otherwise changes will not be saved properly"}

)} {currentBranchName && currentBranchName !== "" && ( You are on branch: {currentBranchName}. )} {branchInfoLoading && Checking branch...}
{currentBranchName === "master" ? ( ) : isAnyCheckoutVersionInProgress && !isCheckingOutVersion ? null : ( )}
)} {/* Why is this pt-0.5? Because the loading bar is h-1 (it always takes space) and we want the vertical spacing to be consistent.*/}
); }