diff --git a/client/src/components/GalaxyAI.vue b/client/src/components/GalaxyAI.vue index cac358d61b6..7f794ee8ac8 100644 --- a/client/src/components/GalaxyAI.vue +++ b/client/src/components/GalaxyAI.vue @@ -396,9 +396,7 @@ function popOutToWindowManager() { } function dockTo(location: "right" | "bottom") { - chatStore.setActiveChatId(currentChatId.value); - chatStore.setLocation(location); - chatStore.showChat(); + chatStore.dockChat(location, currentChatId.value); if (route.path.startsWith("/galaxyai")) { router.push("/"); } diff --git a/client/src/components/GalaxyAI/ChatHistoryPanel.vue b/client/src/components/GalaxyAI/ChatHistoryPanel.vue index 18f94dbea9a..e15aab42dd3 100644 --- a/client/src/components/GalaxyAI/ChatHistoryPanel.vue +++ b/client/src/components/GalaxyAI/ChatHistoryPanel.vue @@ -56,8 +56,7 @@ function handleItemClick(item: ChatHistoryItem, index: number, event: MouseEvent if (chatStore.isCenterMode) { router.push(`/galaxyai/${item.id}`); } else { - chatStore.setActiveChatId(item.id); - chatStore.showChat(); + chatStore.showChat(item.id); } } @@ -65,8 +64,7 @@ function startNewChat() { if (chatStore.isCenterMode) { router.push("/galaxyai/new"); } else { - chatStore.setActiveChatId(null); - chatStore.showChat(); + chatStore.showChat(null); } } diff --git a/client/src/components/GalaxyAI/ChatModeSelector.test.ts b/client/src/components/GalaxyAI/ChatModeSelector.test.ts index 0de7e94287c..629a8e05a9f 100644 --- a/client/src/components/GalaxyAI/ChatModeSelector.test.ts +++ b/client/src/components/GalaxyAI/ChatModeSelector.test.ts @@ -157,38 +157,36 @@ describe("ChatModeSelector", () => { // ── openDockedChat – location ────────────────────────────────────────────── - describe("openDockedChat — location", () => { - it("calls setLocation('right') for side panel button", async () => { + describe("openDockedChat — dockChat call", () => { + it("calls dockChat with 'right' for side panel button", async () => { const { wrapper, store } = mountComponent(); + store.activeChatId = "active-chat"; await getButtons(wrapper).at(1).trigger("click"); - expect(store.setLocation).toHaveBeenCalledWith("right"); + expect(store.dockChat).toHaveBeenCalledWith("right", "active-chat"); }); - it("calls setLocation('bottom') for bottom panel button", async () => { + it("calls dockChat with 'bottom' for bottom panel button", async () => { const { wrapper, store } = mountComponent(); + store.activeChatId = "active-chat"; await getButtons(wrapper).at(2).trigger("click"); - expect(store.setLocation).toHaveBeenCalledWith("bottom"); + expect(store.dockChat).toHaveBeenCalledWith("bottom", "active-chat"); }); - }); - // ── openDockedChat – chat ID resolution ─────────────────────────────────── - - describe("openDockedChat — chat ID resolution", () => { it("uses routedChatId when coming from center mode with exchangeId in route", async () => { mockRoute = { path: "/galaxyai/routed-chat", params: { exchangeId: "routed-chat" } }; const { wrapper, store } = mountComponent(); store.chatLocation = "center"; await getButtons(wrapper).at(1).trigger("click"); - expect(store.showChat).toHaveBeenCalledWith("routed-chat"); + expect(store.dockChat).toHaveBeenCalledWith("right", "routed-chat"); }); - it("uses activeOrLatestId when in center mode but no exchangeId in route", async () => { + it("uses activeChatId fallback when in center mode but no exchangeId in route", async () => { mockRoute = { path: "/galaxyai", params: {} }; const { wrapper, store } = mountComponent(); store.chatLocation = "center"; store.activeChatId = "active-chat"; await getButtons(wrapper).at(1).trigger("click"); - expect(store.showChat).toHaveBeenCalledWith("active-chat"); + expect(store.dockChat).toHaveBeenCalledWith("right", "active-chat"); }); it("uses activeChatId when not in center mode", async () => { @@ -196,7 +194,7 @@ describe("ChatModeSelector", () => { store.chatLocation = "right"; store.activeChatId = "active-chat"; await getButtons(wrapper).at(1).trigger("click"); - expect(store.showChat).toHaveBeenCalledWith("active-chat"); + expect(store.dockChat).toHaveBeenCalledWith("right", "active-chat"); }); it("uses first history item when activeChatId is null but history exists", async () => { @@ -204,7 +202,7 @@ describe("ChatModeSelector", () => { store.activeChatId = null; store.chatHistory = [{ id: "hist-1" } as ChatHistoryItem, { id: "hist-2" } as ChatHistoryItem]; await getButtons(wrapper).at(1).trigger("click"); - expect(store.showChat).toHaveBeenCalledWith("hist-1"); + expect(store.dockChat).toHaveBeenCalledWith("right", "hist-1"); }); it("uses null when no activeChatId and empty history", async () => { @@ -212,7 +210,7 @@ describe("ChatModeSelector", () => { store.activeChatId = null; store.chatHistory = []; await getButtons(wrapper).at(1).trigger("click"); - expect(store.showChat).toHaveBeenCalledWith(null); + expect(store.dockChat).toHaveBeenCalledWith("right", null); }); it("prefers activeChatId over first history item when both present", async () => { @@ -220,7 +218,7 @@ describe("ChatModeSelector", () => { store.activeChatId = "active-chat"; store.chatHistory = [{ id: "hist-1" } as ChatHistoryItem]; await getButtons(wrapper).at(1).trigger("click"); - expect(store.showChat).toHaveBeenCalledWith("active-chat"); + expect(store.dockChat).toHaveBeenCalledWith("right", "active-chat"); }); it("does NOT use routedChatId when not in center mode even with exchangeId in route", async () => { @@ -229,8 +227,8 @@ describe("ChatModeSelector", () => { store.chatLocation = "right"; store.activeChatId = "active-chat"; await getButtons(wrapper).at(1).trigger("click"); - expect(store.showChat).toHaveBeenCalledWith("active-chat"); - expect(store.showChat).not.toHaveBeenCalledWith("some-chat"); + expect(store.dockChat).toHaveBeenCalledWith("right", "active-chat"); + expect(store.dockChat).not.toHaveBeenCalledWith("right", "some-chat"); }); }); }); diff --git a/client/src/components/GalaxyAI/ChatModeSelector.vue b/client/src/components/GalaxyAI/ChatModeSelector.vue index b78ec84c388..113969f1cba 100644 --- a/client/src/components/GalaxyAI/ChatModeSelector.vue +++ b/client/src/components/GalaxyAI/ChatModeSelector.vue @@ -15,7 +15,7 @@ const router = useRouter(); const chatStore = useChatStore(); -const { activeChatId, chatHistory, isBottomPanelOpen, isCenterMode, isRightPanelOpen } = storeToRefs(chatStore); +const { activeChatId, isBottomPanelOpen, isCenterMode, isRightPanelOpen } = storeToRefs(chatStore); const isOnGalaxyAIRoute = computed(() => route.path.startsWith("/galaxyai")); @@ -31,22 +31,15 @@ function openCenterChat() { function openDockedChat(location: "right" | "bottom") { /** Stores an id if there is a `/galaxyai/:exchangeId` route param */ const routedChatId = route.path.includes("galaxyai") ? route.params["exchangeId"] || null : null; - // TODO: What if we just looked at a chat, maybe add a chatId to localStorage for last opened chat? - const activeOrLatestId = chatStore.activeChatId || (chatHistory.value.length > 0 ? chatHistory.value[0]!.id : null); const wasCenterMode = chatStore.isCenterMode; if (isOnGalaxyAIRoute.value) { router.push("/"); } - chatStore.setLocation(location); - if (wasCenterMode && routedChatId) { - chatStore.setActiveChatId(routedChatId); - chatStore.showChat(routedChatId); - } else { - chatStore.setActiveChatId(activeOrLatestId); - chatStore.showChat(activeOrLatestId); - } + // TODO: What if we just looked at a chat, maybe add a chatId to localStorage for last opened chat? + const chatId = wasCenterMode && routedChatId ? routedChatId : chatStore.resolveDockChatId(); + chatStore.dockChat(location, chatId); } diff --git a/client/src/components/GalaxyAI/ChatPanel.vue b/client/src/components/GalaxyAI/ChatPanel.vue index caea896f862..20fd1d3ea66 100644 --- a/client/src/components/GalaxyAI/ChatPanel.vue +++ b/client/src/components/GalaxyAI/ChatPanel.vue @@ -35,8 +35,7 @@ function close() { } function startNewChat() { - chatStore.setActiveChatId(null); - chatStore.showChat(); + chatStore.showChat(null); } diff --git a/client/src/stores/chatStore.ts b/client/src/stores/chatStore.ts index 088235906e9..c9f54a5e736 100644 --- a/client/src/stores/chatStore.ts +++ b/client/src/stores/chatStore.ts @@ -86,6 +86,17 @@ export const useChatStore = defineStore("chatStore", () => { } } + /** Returns the active chat id, falling back to the most recent history item, or null. */ + function resolveDockChatId(): string | null { + return activeChatId.value ?? chatHistory.value[0]?.id ?? null; + } + + /** Sets the chat location and shows the chat with the given id in one step. */ + function dockChat(location: ChatLocation, chatId?: string | null) { + setLocation(location); + showChat(chatId); + } + return { chatHistory, chatLocation, @@ -103,5 +114,7 @@ export const useChatStore = defineStore("chatStore", () => { toggleChat, setLocation, setActiveChatId, + resolveDockChatId, + dockChat, }; });