From f3af524c61135da5666ba598ba34580116df33a1 Mon Sep 17 00:00:00 2001 From: Harald Schilly Date: Tue, 9 Sep 2025 18:07:05 +0200 Subject: [PATCH] frontend/title-bar: only open one AI Assistant dialog -- fixes #8559 --- .../frame-editors/frame-tree/title-bar.tsx | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/packages/frontend/frame-editors/frame-tree/title-bar.tsx b/src/packages/frontend/frame-editors/frame-tree/title-bar.tsx index b7de3bdd21..d53454d9eb 100644 --- a/src/packages/frontend/frame-editors/frame-tree/title-bar.tsx +++ b/src/packages/frontend/frame-editors/frame-tree/title-bar.tsx @@ -205,7 +205,10 @@ export function FrameTitleBar(props: FrameTitleBarProps) { const [close_and_halt_confirm, set_close_and_halt_confirm] = useState(false); - const [showAI, setShowAI] = useState(false); + const [showAIDialogs, setShowAIDialogs] = useState<{ + main: boolean; + popover: boolean; + }>({ main: false, popover: false }); const [showNewAI, setShowNewAI] = useState(false); const [helpSearch, setHelpSearch] = useState(""); @@ -235,7 +238,8 @@ export function FrameTitleBar(props: FrameTitleBarProps) { new ManageCommands({ props, studentProjectFunctionality: student_project_functionality, - setShowAI, + setShowAI: (val: boolean) => + setShowAIDialogs((prev) => ({ ...prev, main: val })), setShowNewAI, helpSearch, setHelpSearch, @@ -248,7 +252,7 @@ export function FrameTitleBar(props: FrameTitleBarProps) { student_project_functionality, helpSearch, setHelpSearch, - setShowAI, + setShowAIDialogs, setShowNewAI, read_only, editorSettings, @@ -579,7 +583,7 @@ export function FrameTitleBar(props: FrameTitleBarProps) { ); } - function renderAssistant(noLabel): Rendered { + function renderAssistant(noLabel, where: "main" | "popover"): Rendered { if ( !manageCommands.isVisible("chatgpt") || !redux.getStore("projects").hasLanguageModelEnabled(props.project_id) @@ -590,11 +594,13 @@ export function FrameTitleBar(props: FrameTitleBarProps) { { + setShowAIDialogs((prev) => ({ ...prev, [where]: value })); + }} project_id={props.project_id} buttonRef={getTourRef("chatgpt")} - key={"ai-button"} + key={`ai-button-${where}`} id={props.id} actions={props.actions} buttonSize={button_size()} @@ -641,7 +647,7 @@ export function FrameTitleBar(props: FrameTitleBarProps) { ); } - function renderSaveTimetravelGroup(): Rendered { + function renderSaveTimetravelGroup(where: "main" | "popover"): Rendered { if (props.type == "chat") { // these buttons don't make much sense for side chat. return; @@ -651,7 +657,7 @@ export function FrameTitleBar(props: FrameTitleBarProps) { let x; if ((x = renderSaveButton(noLabel))) v.push(x); if ((x = renderTimeTravel(noLabel))) v.push(x); - if ((x = renderAssistant(noLabel))) v.push(x); + if ((x = renderAssistant(noLabel, where))) v.push(x); if ((x = renderComputeServer(noLabel))) v.push(x); if (v.length == 1) return v[0]; if (v.length > 0) { @@ -754,7 +760,11 @@ export function FrameTitleBar(props: FrameTitleBarProps) { // seems too horrible right now since it is a selector. } - function renderButtons(style?: CSS, noRefs?): Rendered { + function renderButtons( + style?: CSS, + noRefs?, + where: "main" | "popover" = "main", + ): Rendered { if (!is_active) { return (
@@ -784,7 +794,7 @@ export function FrameTitleBar(props: FrameTitleBarProps) { } const v: (React.JSX.Element | undefined | null)[] = []; - v.push(renderSaveTimetravelGroup()); + v.push(renderSaveTimetravelGroup(where)); if (props.title != null) { v.push(renderTitle()); } @@ -841,7 +851,7 @@ export function FrameTitleBar(props: FrameTitleBarProps) { } return ( - {renderButtons({ maxHeight: "50vh", display: "block" }, true)} + {renderButtons( + { maxHeight: "50vh", display: "block" }, + true, + "popover", + )}
{renderFrameControls()}