mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
feat(frontend): persist drawer open/close state on page refresh (#10935)
Co-authored-by: sp.wack <83104063+amanape@users.noreply.github.com>
This commit is contained in:
@@ -57,18 +57,13 @@ export function ConversationMain() {
|
||||
<PanelGroup
|
||||
direction="horizontal"
|
||||
className="grow h-full min-h-0 min-w-0"
|
||||
autoSaveId="react-resizable-panels:layout"
|
||||
>
|
||||
<Panel
|
||||
defaultSize={50}
|
||||
minSize={30}
|
||||
maxSize={80}
|
||||
className="overflow-hidden bg-base"
|
||||
>
|
||||
<Panel minSize={30} maxSize={80} className="overflow-hidden bg-base">
|
||||
<ChatInterfaceWrapper isRightPanelShown={isRightPanelShown} />
|
||||
</Panel>
|
||||
<PanelResizeHandle className="cursor-ew-resize" />
|
||||
<Panel
|
||||
defaultSize={50}
|
||||
minSize={20}
|
||||
maxSize={70}
|
||||
className="flex flex-col overflow-hidden"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useLocalStorage } from "@uidotdev/usehooks";
|
||||
import JupyterIcon from "#/icons/jupyter.svg?react";
|
||||
import TerminalIcon from "#/icons/terminal.svg?react";
|
||||
import GlobeIcon from "#/icons/globe.svg?react";
|
||||
@@ -15,6 +16,7 @@ import { VSCodeTooltipContent } from "./vscode-tooltip-content";
|
||||
import {
|
||||
setHasRightPanelToggled,
|
||||
setSelectedTab,
|
||||
setIsRightPanelShown,
|
||||
type ConversationTab,
|
||||
} from "#/state/conversation-slice";
|
||||
import { RootState } from "#/store";
|
||||
@@ -28,10 +30,30 @@ export function ConversationTabs() {
|
||||
(state: RootState) => state.conversation,
|
||||
);
|
||||
|
||||
// Persist selectedTab and isRightPanelShown in localStorage
|
||||
const [persistedSelectedTab, setPersistedSelectedTab] =
|
||||
useLocalStorage<ConversationTab | null>(
|
||||
"conversation-selected-tab",
|
||||
"editor",
|
||||
);
|
||||
|
||||
const [persistedIsRightPanelShown, setPersistedIsRightPanelShown] =
|
||||
useLocalStorage<boolean>("conversation-right-panel-shown", true);
|
||||
|
||||
const onTabChange = (value: ConversationTab | null) => {
|
||||
dispatch(setSelectedTab(value));
|
||||
// Persist the selected tab to localStorage
|
||||
setPersistedSelectedTab(value);
|
||||
};
|
||||
|
||||
// Initialize Redux state from localStorage on component mount
|
||||
useEffect(() => {
|
||||
// Initialize selectedTab from localStorage if available
|
||||
dispatch(setSelectedTab(persistedSelectedTab));
|
||||
dispatch(setIsRightPanelShown(persistedIsRightPanelShown));
|
||||
dispatch(setHasRightPanelToggled(persistedIsRightPanelShown));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handlePanelVisibilityChange = () => {
|
||||
if (isRightPanelShown) {
|
||||
@@ -51,11 +73,13 @@ export function ConversationTabs() {
|
||||
if (selectedTab === tab && isRightPanelShown) {
|
||||
// If clicking the same active tab, close the drawer
|
||||
dispatch(setHasRightPanelToggled(false));
|
||||
setPersistedIsRightPanelShown(false);
|
||||
} else {
|
||||
// If clicking a different tab or drawer is closed, open drawer and select tab
|
||||
onTabChange(tab);
|
||||
if (!isRightPanelShown) {
|
||||
dispatch(setHasRightPanelToggled(true));
|
||||
setPersistedIsRightPanelShown(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,8 +117,6 @@ export const conversationSlice = createSlice({
|
||||
},
|
||||
// Reset conversation state (useful for cleanup)
|
||||
resetConversationState: (state) => {
|
||||
state.selectedTab = "editor";
|
||||
state.isRightPanelShown = true;
|
||||
state.shouldHideSuggestions = false;
|
||||
},
|
||||
setHasRightPanelToggled: (state, action) => {
|
||||
|
||||
Reference in New Issue
Block a user