diff --git a/ui/desktop/src/components/ChatInput.tsx b/ui/desktop/src/components/ChatInput.tsx index 7467dfe3c176..3b4e2fe24370 100644 --- a/ui/desktop/src/components/ChatInput.tsx +++ b/ui/desktop/src/components/ChatInput.tsx @@ -1179,7 +1179,7 @@ export default function ChatInput({ )} {/* Secondary actions and controls row below input */} -
+
{/* Directory path */} 0} className="mr-0" />
diff --git a/ui/desktop/src/components/CheckpointActions.tsx b/ui/desktop/src/components/CheckpointActions.tsx index 90b401513ca7..36a62274fc8d 100644 --- a/ui/desktop/src/components/CheckpointActions.tsx +++ b/ui/desktop/src/components/CheckpointActions.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; import { ResourceContent } from '../types/message'; +import { useSidecar } from './SidecarLayout'; interface CheckpointActionsProps { checkpointContent: ResourceContent; @@ -7,6 +8,7 @@ interface CheckpointActionsProps { export default function CheckpointActions({ checkpointContent }: CheckpointActionsProps) { const [showDiff, setShowDiff] = useState(false); + const sidecar = useSidecar(); // Parse the checkpoint payload let checkpointData: { @@ -23,7 +25,21 @@ export default function CheckpointActions({ checkpointContent }: CheckpointActio } const handleViewDiff = () => { - setShowDiff(!showDiff); + if (sidecar && checkpointData.diff) { + // Check if diff viewer is already active + if (sidecar.activeView === 'diff') { + // If diff viewer is open, close it + sidecar.hideDiffViewer(); + setShowDiff(false); + } else { + // Show diff in sidecar + sidecar.showDiffViewer(checkpointData.diff, checkpointData.file || 'File'); + setShowDiff(true); + } + } else { + // Fallback to inline diff display + setShowDiff(!showDiff); + } }; const handleRestore = async () => { @@ -62,7 +78,7 @@ export default function CheckpointActions({ checkpointContent }: CheckpointActio onClick={handleViewDiff} className="text-xs px-2 py-1 bg-bgStandard hover:bg-bgSubtle border border-borderSubtle rounded transition-colors" > - {showDiff ? 'Hide Diff' : 'View Diff'} + {sidecar && sidecar.activeView === 'diff' ? 'Hide Diff' : 'View Diff'} {checkpointData.checkpoint && ( - View diff + + {sidecar.activeView === 'diff' ? 'Hide diff' : 'View diff'} +
)} diff --git a/ui/desktop/src/components/SidecarLayout.tsx b/ui/desktop/src/components/SidecarLayout.tsx index ee874ad64c23..01a94f33f43e 100644 --- a/ui/desktop/src/components/SidecarLayout.tsx +++ b/ui/desktop/src/components/SidecarLayout.tsx @@ -304,8 +304,8 @@ export function SidecarProvider({ children, showSidecar = true }: SidecarProvide // Import and use the window manager hook const { toggleWindow } = useWindowManager({ - expandPercentage: 100, - maxWidthForExpansion: 2200, + expandPercentage: 60, + maxWidthForExpansion: 1200, transitionDuration: 300, }); @@ -323,8 +323,10 @@ export function SidecarProvider({ children, showSidecar = true }: SidecarProvide setActiveView(view.id); }; - const hideView = () => { + const hideView = async () => { setActiveView(null); + // Collapse window when hiding sidecar + await toggleWindow(); }; const showDiffViewer = (content: string, fileName = 'File') => { @@ -338,10 +340,12 @@ export function SidecarProvider({ children, showSidecar = true }: SidecarProvide showView(diffView); }; - const hideDiffViewer = () => { + const hideDiffViewer = async () => { setViews((prev) => prev.filter((v) => v.id !== 'diff')); if (activeView === 'diff') { setActiveView(null); + // Collapse window when hiding diff viewer + await toggleWindow(); } }; diff --git a/ui/desktop/src/hooks/useWindowManager.ts b/ui/desktop/src/hooks/useWindowManager.ts index c08a2335071f..4dfe7806cc38 100644 --- a/ui/desktop/src/hooks/useWindowManager.ts +++ b/ui/desktop/src/hooks/useWindowManager.ts @@ -177,12 +177,6 @@ export function useWindowManager(options: WindowManagerOptions = {}): WindowMana return; } - // Don't resize if window is already expanded - if (windowState.isExpanded) { - console.log('Window is already expanded, skipping resize operation'); - return; - } - try { resizeInProgressRef.current = true; @@ -191,33 +185,52 @@ export function useWindowManager(options: WindowManagerOptions = {}): WindowMana isTransitioning: true, })); - // Only expanding logic remains since we skip when already expanded - if (!canExpand) { - console.log('Window too wide for expansion, skipping resize'); - setWindowState((prev) => ({ - ...prev, - isTransitioning: false, - })); - // Still mount the component even if we don't resize - setIsComponentMounted(true); - return; - } + if (windowState.isExpanded) { + // Collapse the window back to original size + console.log('Window is expanded, collapsing back to original size'); + + const success = await window.electron.resizeWindow(0); // 0 means reset to original size + + if (success) { + setWindowState((prev) => ({ + ...prev, + isExpanded: false, + currentWidth: prev.originalWidth, + isTransitioning: false, + })); + } else { + throw new Error('Failed to resize window for collapse'); + } + } else { + // Expand the window + if (!canExpand) { + console.log('Window too wide for expansion, skipping resize but showing sidecar'); + setWindowState((prev) => ({ + ...prev, + isExpanded: true, // Mark as expanded even though we didn't resize + isTransitioning: false, + })); + // Still mount the component even if we don't resize + setIsComponentMounted(true); + return; + } - const success = await window.electron.resizeWindow(opts.expandPercentage); + const success = await window.electron.resizeWindow(opts.expandPercentage); - if (success) { - const newWidth = Math.floor(windowState.currentWidth * (1 + opts.expandPercentage / 100)); + if (success) { + const newWidth = Math.floor(windowState.currentWidth * (1 + opts.expandPercentage / 100)); - setWindowState((prev) => ({ - ...prev, - isExpanded: true, - currentWidth: newWidth, - isTransitioning: false, - })); + setWindowState((prev) => ({ + ...prev, + isExpanded: true, + currentWidth: newWidth, + isTransitioning: false, + })); - // Component will be mounted by the useEffect above - } else { - throw new Error('Failed to resize window for expansion'); + // Component will be mounted by the useEffect above + } else { + throw new Error('Failed to resize window for expansion'); + } } } catch (error) { console.error('Error during window toggle:', error);