diff --git a/apps/desktop/src/app/right-sidebar/terminal/persistent.test.tsx b/apps/desktop/src/app/right-sidebar/terminal/persistent.test.tsx index 638beaae1a8d..cc6b15c1507f 100644 --- a/apps/desktop/src/app/right-sidebar/terminal/persistent.test.tsx +++ b/apps/desktop/src/app/right-sidebar/terminal/persistent.test.tsx @@ -14,6 +14,7 @@ vi.mock('./workspace', () => ({ let resizeObserverCallback: ResizeObserverCallback | null = null let mutationObserverCallback: MutationCallback | null = null +let mutationObserveCalls: Array<{ options?: MutationObserverInit; target: Node }> = [] let root: Root | null = null let container: HTMLDivElement | null = null let windowStateCallback: ((payload: { isMinimized?: boolean; isVisible?: boolean }) => void) | null = null @@ -128,6 +129,7 @@ describe('PersistentTerminal rect tracking', () => { installWindowStateBridge() resizeObserverCallback = null mutationObserverCallback = null + mutationObserveCalls = [] vi.stubGlobal( 'ResizeObserver', class { @@ -148,7 +150,9 @@ describe('PersistentTerminal rect tracking', () => { } disconnect = vi.fn() - observe = vi.fn() + observe = vi.fn((target: Node, options?: MutationObserverInit) => { + mutationObserveCalls.push({ options, target }) + }) takeRecords = vi.fn(() => []) } as unknown as typeof MutationObserver ) @@ -206,6 +210,8 @@ describe('PersistentTerminal rect tracking', () => { render() + expect(mutationObserveCalls.some(call => call.options?.subtree === true)).toBe(true) + act(() => { raf.runNext() }) @@ -287,4 +293,18 @@ describe('PersistentTerminal rect tracking', () => { }) expect(raf.pending()).toBe(0) }) + + it('does not schedule an initial frame when mounted while unfocused', () => { + const raf = installRaf() + vi.mocked(document.hasFocus).mockReturnValue(false) + vi.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockReturnValue(rect(10, 20, 200, 100)) + + render() + + expect(raf.request).not.toHaveBeenCalled() + + act(() => window.dispatchEvent(new Event('focus'))) + + expect(raf.pending()).toBe(1) + }) }) diff --git a/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx b/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx index 5827ec0a8795..3fe2edb04a78 100644 --- a/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx +++ b/apps/desktop/src/app/right-sidebar/terminal/persistent.tsx @@ -161,6 +161,8 @@ export function PersistentTerminal({ onAddSelectionToChat }: PersistentTerminalP scheduleMeasure() }) + pauseController = createRendererLoopPauseController(handleVisibilityChange) + if (measure()) { scheduleMeasure() } @@ -171,13 +173,13 @@ export function PersistentTerminal({ onAddSelectionToChat }: PersistentTerminalP positionObserver?.observe(node, { attributeFilter: ['class', 'style', 'hidden', 'aria-hidden', 'data-state'], attributes: true, - childList: true + childList: true, + subtree: true }) } window.addEventListener('resize', scheduleMeasure) window.addEventListener('scroll', scheduleMeasure, true) - pauseController = createRendererLoopPauseController(handleVisibilityChange) return () => { stopped = true