From e1b283886feee6d505966c6caa50eb5b41e35f98 Mon Sep 17 00:00:00 2001 From: Neha Prasad Date: Fri, 5 Dec 2025 20:05:10 +0530 Subject: [PATCH] fix: conversation tab state sync across browser tabs (#11680) Co-authored-by: amanape <83104063+amanape@users.noreply.github.com> --- .../conversation-tabs/conversation-tabs.tsx | 13 ++++-- frontend/src/state/conversation-store.ts | 44 +++++++++++++++++-- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/features/conversation/conversation-tabs/conversation-tabs.tsx b/frontend/src/components/features/conversation/conversation-tabs/conversation-tabs.tsx index e84466bd22..eedb9010e8 100644 --- a/frontend/src/components/features/conversation/conversation-tabs/conversation-tabs.tsx +++ b/frontend/src/components/features/conversation/conversation-tabs/conversation-tabs.tsx @@ -19,8 +19,10 @@ import { } from "#/state/conversation-store"; import { ConversationTabsContextMenu } from "./conversation-tabs-context-menu"; import { USE_PLANNING_AGENT } from "#/utils/feature-flags"; +import { useConversationId } from "#/hooks/use-conversation-id"; export function ConversationTabs() { + const { conversationId } = useConversationId(); const { selectedTab, isRightPanelShown, @@ -30,18 +32,21 @@ export function ConversationTabs() { const [isMenuOpen, setIsMenuOpen] = useState(false); - // Persist selectedTab and isRightPanelShown in localStorage + // Persist selectedTab and isRightPanelShown in localStorage per conversation const [persistedSelectedTab, setPersistedSelectedTab] = useLocalStorage( - "conversation-selected-tab", + `conversation-selected-tab-${conversationId}`, "editor", ); const [persistedIsRightPanelShown, setPersistedIsRightPanelShown] = - useLocalStorage("conversation-right-panel-shown", true); + useLocalStorage( + `conversation-right-panel-shown-${conversationId}`, + true, + ); const [persistedUnpinnedTabs] = useLocalStorage( - "conversation-unpinned-tabs", + `conversation-unpinned-tabs-${conversationId}`, [], ); diff --git a/frontend/src/state/conversation-store.ts b/frontend/src/state/conversation-store.ts index cfbacc1f9a..a8edd16f6a 100644 --- a/frontend/src/state/conversation-store.ts +++ b/frontend/src/state/conversation-store.ts @@ -61,10 +61,48 @@ interface ConversationActions { type ConversationStore = ConversationState & ConversationActions; -// Helper function to get initial right panel state from localStorage +const getConversationIdFromLocation = (): string | null => { + if (typeof window === "undefined") { + return null; + } + + const match = window.location.pathname.match(/\/conversations\/([^/]+)/); + return match ? match[1] : null; +}; + +const parseStoredBoolean = (value: string | null): boolean | null => { + if (value === null) { + return null; + } + + try { + return JSON.parse(value); + } catch { + return null; + } +}; + const getInitialRightPanelState = (): boolean => { - const stored = localStorage.getItem("conversation-right-panel-shown"); - return stored !== null ? JSON.parse(stored) : true; + if (typeof window === "undefined") { + return true; + } + + const conversationId = getConversationIdFromLocation(); + const keysToCheck = conversationId + ? [`conversation-right-panel-shown-${conversationId}`] + : []; + + // Fallback to legacy global key for users who haven't switched tabs yet + keysToCheck.push("conversation-right-panel-shown"); + + for (const key of keysToCheck) { + const parsed = parseStoredBoolean(localStorage.getItem(key)); + if (parsed !== null) { + return parsed; + } + } + + return true; }; export const useConversationStore = create()(