Files
gemini-cli/packages/cli/src/ui/hooks/useAlternateBuffer.ts
T
jacob314 8956d77da4 fix(ui): use centralized queue for all transient hints and warnings
This commit properly implements the transient message queue in AppContainer, fixing flickering issues caused when the UI exceeds terminal height in legacy non-alternate buffer mode. By introducing useLegacyNonAlternateBufferMode, the timer for transient messages (like the markdown toggle and Ctrl+O overflow hint) pauses when an overflow happens in standard mode. This ensures hints remain on screen without causing infinite loops or terminal jumping.

Additionally:
- Consolidates older scattered state (queueErrorMessage, showEscapePrompt, etc) into the single transientMessageQueue.
- Standardizes transient message payloads with a uniform format.
- Extensively updates tests to handle these context changes correctly.

Fixes #21824
2026-03-10 15:02:50 -07:00

46 lines
1.5 KiB
TypeScript

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { useState, useLayoutEffect, type RefObject } from 'react';
import { useConfig } from '../contexts/ConfigContext.js';
import type { Config } from '@google/gemini-cli-core';
import { type DOMElement, measureElement } from 'ink';
import { useTerminalSize } from './useTerminalSize.js';
export const isAlternateBufferEnabled = (config: Config): boolean =>
config.getUseAlternateBuffer();
// This is read from Config so that the UI reads the same value per application session
export const useAlternateBuffer = (): boolean => {
const config = useConfig();
return isAlternateBufferEnabled(config);
};
export const useLegacyNonAlternateBufferMode = (
rootUiRef: RefObject<DOMElement | null>,
isAlternateBuffer: boolean,
): boolean => {
const { rows: terminalHeight } = useTerminalSize();
const [isOverflowing, setIsOverflowing] = useState(false);
useLayoutEffect(() => {
if (isAlternateBuffer || !rootUiRef.current) {
if (isOverflowing) setIsOverflowing(false);
return;
}
const measurement = measureElement(rootUiRef.current);
// If the interactive UI is taller than the terminal height, we have a problem.
const currentlyOverflowing = measurement.height >= terminalHeight;
if (currentlyOverflowing !== isOverflowing) {
setIsOverflowing(currentlyOverflowing);
}
}, [isAlternateBuffer, rootUiRef, terminalHeight, isOverflowing]);
return !isAlternateBuffer && isOverflowing;
};