Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 41 additions & 7 deletions packages/cli/src/ui/AppContainer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1092,13 +1092,10 @@ describe('AppContainer State Management', () => {
expect(capturedUIState.useTerminalBuffer).toBe(true);
});

// #4891 changed the resize contract: width changes now trigger ONE full
// clearTerminal after RESIZE_REPAINT_SETTLE_MS (trailing-edge debounce),
// instead of never (#3967) or per-event (pre-#3967). This test pins the
// synchronous half: no immediate clear during the burst. The settle-time
// half is not observable here — ink-testing-library's rerender does not
// flush update-time passive effects — and is covered by
// useResizeSettleRepaint.test.ts.
// Resize no longer triggers a clearTerminal or history remount (#8004).
// The old settle → refreshStatic path caused a scroll storm; the dynamic
// region now re-renders via useTerminalSize alone. This test pins that
// no synchronous clear fires during a width change.
it('does not clear the terminal synchronously on width change', () => {
vi.spyOn(mockConfig, 'initialize').mockResolvedValue(undefined);
mockedUseTerminalSize.mockReturnValue({ columns: 80, rows: 24 });
Expand Down Expand Up @@ -1127,6 +1124,43 @@ describe('AppContainer State Management', () => {
);
});

it('does not repaint static history after a resize settles (#8004)', () => {
vi.useFakeTimers();
vi.spyOn(mockConfig, 'initialize').mockResolvedValue(undefined);
mockedUseTerminalSize.mockReturnValue({ columns: 80, rows: 24 });
const { rerender } = render(
<AppContainer
config={mockConfig}
settings={mockSettings}
version="1.0.0"
initializationResult={mockInitResult}
/>,
);
mockStdout.write.mockClear();

mockedUseTerminalSize.mockReturnValue({ columns: 100, rows: 24 });
rerender(
<AppContainer
config={mockConfig}
settings={mockSettings}
version="1.0.0"
initializationResult={mockInitResult}
/>,
);

// Advance well past the old RESIZE_REPAINT_SETTLE_MS (200ms) debounce.
// The removed settle -> refreshStatic path wrote clearTerminal here; the
// new contract never does, so a future re-introduction would fail this.
act(() => {
vi.advanceTimersByTime(500);
});

expect(mockStdout.write).not.toHaveBeenCalledWith(
ansiEscapes.clearTerminal,
);
vi.useRealTimers();
});

it('handleClearScreen avoids a second clearTerminal write', () => {
const clearSpy = vi.spyOn(console, 'clear').mockImplementation(() => {});

Expand Down
9 changes: 6 additions & 3 deletions packages/cli/src/ui/AppContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ const MCP_BATCH_FLUSH_MS = 16;
const STARTUP_PROFILE_FINALIZE_CAP_MS = 35_000;
import { useHistory } from './hooks/useHistoryManager.js';
import { useMemoryMonitor } from './hooks/useMemoryMonitor.js';
import { useResizeSettleRepaint } from './hooks/useResizeSettleRepaint.js';
import { useWakeRepaint } from './hooks/use-wake-repaint.js';
import { useThemeCommand } from './hooks/useThemeCommand.js';
import { useFeedbackDialog } from './hooks/useFeedbackDialog.js';
Expand Down Expand Up @@ -3245,8 +3244,12 @@ export const AppContainer = (props: AppContainerProps) => {
}
}, [terminalWidth, availableTerminalHeight, activePtyId]);

// Repaint static history on the trailing edge of a resize burst (#4891).
useResizeSettleRepaint(terminalWidth, refreshStatic);
// Resize no longer repaints static history (#8004). The old settle →
// refreshStatic path wrote clearTerminal (destroying scrollback) and remounted
// <Static>, re-emitting all history in 50-item chunks — a scroll storm when
// the terminal's resize animation exceeded the debounce window (e.g. Ghostty
// panel toggle). Ink's dynamic region already re-renders on width changes via
// useTerminalSize; modern terminals reflow scrollback natively.

// Repaint after the process resumes from OS sleep / suspend (lid close,
// display sleep, Ctrl+Z → fg). The terminal's screen buffer is stale but
Expand Down
102 changes: 0 additions & 102 deletions packages/cli/src/ui/hooks/useResizeSettleRepaint.test.ts

This file was deleted.

50 changes: 0 additions & 50 deletions packages/cli/src/ui/hooks/useResizeSettleRepaint.ts

This file was deleted.

Loading