From 6a173211b0b11503fe8939523a800bc7681cb6c9 Mon Sep 17 00:00:00 2001 From: HearingSmile <41669762+bigcoder84@users.noreply.github.com> Date: Wed, 27 May 2026 01:30:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(desktop):=20toggle=20browser=20icon=20and?= =?UTF-8?q?=20preserve=20webview=20state=20on=20coll=E2=80=A6=20(#1424)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(desktop): toggle browser icon and preserve webview state on collapse * fix(desktop): stabilize context panel collapse behavior --------- Co-authored-by: Bohdan Triapitsyn --- .../ui/src/components/layout/ContextPanel.tsx | 86 ++++++++++++++----- packages/ui/src/components/layout/Header.tsx | 27 +++++- packages/ui/src/stores/useUIStore.ts | 2 +- 3 files changed, 92 insertions(+), 23 deletions(-) diff --git a/packages/ui/src/components/layout/ContextPanel.tsx b/packages/ui/src/components/layout/ContextPanel.tsx index 1571fb37..23368bc4 100644 --- a/packages/ui/src/components/layout/ContextPanel.tsx +++ b/packages/ui/src/components/layout/ContextPanel.tsx @@ -23,7 +23,7 @@ import { Icon } from "@/components/icon/Icon"; import { OpenChamberLogo } from "@/components/ui/OpenChamberLogo"; import { invokeDesktopCommand } from '@/lib/desktopNative'; -const CONTEXT_PANEL_MIN_WIDTH = 360; +const CONTEXT_PANEL_MIN_WIDTH = 380; const CONTEXT_PANEL_MAX_WIDTH = 1400; const CONTEXT_PANEL_DEFAULT_WIDTH = 600; const CONTEXT_TAB_LABEL_MAX_CHARS = 24; @@ -1588,6 +1588,7 @@ export const ContextPanel: React.FC = () => { const width = clampWidth(panelState?.width ?? CONTEXT_PANEL_DEFAULT_WIDTH); const [isResizing, setIsResizing] = React.useState(false); + const [suppressWidthTransition, setSuppressWidthTransition] = React.useState(false); const startXRef = React.useRef(0); const startWidthRef = React.useRef(width); const resizingWidthRef = React.useRef(null); @@ -1595,6 +1596,41 @@ export const ContextPanel: React.FC = () => { const panelRef = React.useRef(null); const chatFrameRefs = React.useRef>(new Map()); const wasOpenRef = React.useRef(false); + const previousIsOpenRef = React.useRef(isOpen); + const suppressWidthTransitionFrameRef = React.useRef(null); + + const suppressWidthTransitionForFrame = React.useCallback(() => { + setSuppressWidthTransition(true); + if (suppressWidthTransitionFrameRef.current !== null) { + window.cancelAnimationFrame(suppressWidthTransitionFrameRef.current); + } + suppressWidthTransitionFrameRef.current = window.requestAnimationFrame(() => { + suppressWidthTransitionFrameRef.current = null; + setSuppressWidthTransition(false); + }); + }, []); + + React.useEffect(() => () => { + if (suppressWidthTransitionFrameRef.current !== null) { + window.cancelAnimationFrame(suppressWidthTransitionFrameRef.current); + } + }, []); + + React.useLayoutEffect(() => { + const wasOpen = previousIsOpenRef.current; + previousIsOpenRef.current = isOpen; + + if (!isOpen) { + setSuppressWidthTransition(false); + return; + } + + if (wasOpen) { + return; + } + + suppressWidthTransitionForFrame(); + }, [isOpen, suppressWidthTransitionForFrame]); React.useEffect(() => { if (!isOpen || wasOpenRef.current) { @@ -1666,11 +1702,13 @@ export const ContextPanel: React.FC = () => { } const finalWidth = clampWidthToAvailableSpace(resizingWidthRef.current ?? width, panelRef.current); + suppressWidthTransitionForFrame(); + applyLiveWidth(finalWidth); + resizingWidthRef.current = finalWidth; + setContextPanelWidth(directoryKey, finalWidth); setIsResizing(false); activeResizePointerIDRef.current = null; - resizingWidthRef.current = null; - setContextPanelWidth(directoryKey, finalWidth); - }, [directoryKey, setContextPanelWidth, width]); + }, [applyLiveWidth, directoryKey, setContextPanelWidth, suppressWidthTransitionForFrame, width]); React.useEffect(() => { if (!isResizing) { @@ -1910,36 +1948,44 @@ export const ContextPanel: React.FC = () => { ); - if (!isOpen) { - return null; - } - - const panelStyle: React.CSSProperties = isExpanded + const panelStyle: React.CSSProperties = !isOpen ? { - ['--oc-context-panel-width' as string]: '100%', - width: '100%', - minWidth: '100%', - maxWidth: '100%', - } - : { - width: 'min(var(--oc-context-panel-width), 100%)', - minWidth: `min(${CONTEXT_PANEL_MIN_WIDTH}px, 100%)`, - maxWidth: '100%', ['--oc-context-panel-width' as string]: `${isResizing ? (resizingWidthRef.current ?? width) : width}px`, - }; + width: 0, + minWidth: 0, + maxWidth: 0, + opacity: 0, + overflow: 'hidden', + visibility: 'hidden', + } + : isExpanded + ? { + ['--oc-context-panel-width' as string]: '100%', + width: '100%', + minWidth: '100%', + maxWidth: '100%', + } + : { + width: 'min(var(--oc-context-panel-width), 100%)', + minWidth: `min(${CONTEXT_PANEL_MIN_WIDTH}px, 100%)`, + maxWidth: '100%', + ['--oc-context-panel-width' as string]: `${isResizing ? (resizingWidthRef.current ?? width) : width}px`, + }; return (