import { type EnvironmentId, type EditorId, type ProjectScript, type ResolvedKeybindingsConfig, type ThreadId, } from "@t3tools/contracts"; import { scopeThreadRef } from "@t3tools/client-runtime/environment"; import { memo } from "react"; import GitActionsControl from "../GitActionsControl"; import { type DraftId } from "~/composerDraftStore"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import ProjectScriptsControl, { type NewProjectScriptInput, type ProjectScriptActionResult, } from "../ProjectScriptsControl"; import { OpenInPicker } from "./OpenInPicker"; import { usePrimaryEnvironmentId } from "../../state/environments"; import { useT3ProjectFileScripts } from "~/hooks/useT3ProjectFileScripts"; import { ProjectFavicon } from "../ProjectFavicon"; import { cn } from "~/lib/utils"; interface ChatHeaderProps { activeThreadEnvironmentId: EnvironmentId; activeThreadId: ThreadId; draftId?: DraftId; activeThreadTitle: string; activeProjectName: string | undefined; activeProjectCwd: string | null; openInCwd: string | null; activeProjectScripts: ReadonlyArray | undefined; preferredScriptId: string | null; keybindings: ResolvedKeybindingsConfig; availableEditors: ReadonlyArray; rightPanelOpen: boolean; gitCwd: string | null; onRunProjectScript: (script: ProjectScript) => void; onAddProjectScript: (input: NewProjectScriptInput) => Promise; onUpdateProjectScript: ( scriptId: string, input: NewProjectScriptInput, ) => Promise; onDeleteProjectScript: (scriptId: string) => Promise; } export function shouldShowOpenInPicker(input: { readonly activeProjectName: string | undefined; readonly activeThreadEnvironmentId: EnvironmentId; readonly primaryEnvironmentId: EnvironmentId | null; }): boolean { return ( Boolean(input.activeProjectName) && input.primaryEnvironmentId !== null && input.activeThreadEnvironmentId === input.primaryEnvironmentId ); } export const ChatHeader = memo(function ChatHeader({ activeThreadEnvironmentId, activeThreadId, draftId, activeThreadTitle, activeProjectName, activeProjectCwd, openInCwd, activeProjectScripts, preferredScriptId, keybindings, availableEditors, rightPanelOpen, gitCwd, onRunProjectScript, onAddProjectScript, onUpdateProjectScript, onDeleteProjectScript, }: ChatHeaderProps) { const primaryEnvironmentId = usePrimaryEnvironmentId(); const fileScripts = useT3ProjectFileScripts( activeThreadEnvironmentId, activeProjectScripts ? activeProjectCwd : null, ); const showOpenInPicker = shouldShowOpenInPicker({ activeProjectName, activeThreadEnvironmentId, primaryEnvironmentId, }); return (
{/* The project always leads the header: knowing which project a thread lives in is priority zero, and the thread title alone doesn't answer it. */} {activeProjectName ? ( {activeProjectName} / ) : null} {activeThreadTitle} } /> {activeThreadTitle}
{activeProjectScripts && ( )} {showOpenInPicker && ( )} {activeProjectName && ( )}
); });