mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-17 05:20:23 -07:00
feat: add config and keybindings for new ink terminal buffer mode
test: update test utils and resolve snapshot differences for ink changes feat: refactor VirtualizedList to support static rendering and terminal buffers feat: wire up AppContainer mouse mode and recording state for ink buffer Fix stale ref in ScrollProvider breaking scrolling. The ScrollProvider was getting stuck with a stale reference because the `scrollables` Map was being registered and unregistered whenever the entry identity changed. The underlying `ScrollableList` component dynamically created a new ID which caused React remount cycles, while the `ScrollProvider` itself suffered from state lag where the event handler ref was one tick behind the actual registration. This commit resolves these issues by: 1. Adding a stable `id` and `key` to `ScrollableList` in `MainContent.tsx` 2. Making `scrollablesRef` synchronously update in `ScrollProvider.tsx` 3. Using a proxy entry in `useScrollable` to avoid constant re-registering. chore: add useEffect cleanup for ResizeObservers Checkpoint fixing terminal buffer support. Termina Serializer Optimization
This commit is contained in:
@@ -12,6 +12,7 @@ import { useAppContext } from '../contexts/AppContext.js';
|
||||
import { AppHeader } from './AppHeader.js';
|
||||
|
||||
import { useAlternateBuffer } from '../hooks/useAlternateBuffer.js';
|
||||
import { useConfig } from '../contexts/ConfigContext.js';
|
||||
import {
|
||||
SCROLL_TO_ITEM_END,
|
||||
type VirtualizedListRef,
|
||||
@@ -34,6 +35,11 @@ export const MainContent = () => {
|
||||
const { version } = useAppContext();
|
||||
const uiState = useUIState();
|
||||
const isAlternateBuffer = useAlternateBuffer();
|
||||
const config = useConfig();
|
||||
const useTerminalBuffer =
|
||||
typeof config.getUseTerminalBuffer === 'function'
|
||||
? config.getUseTerminalBuffer()
|
||||
: false;
|
||||
|
||||
const confirmingTool = useConfirmingTool();
|
||||
const showConfirmationQueue = confirmingTool !== null;
|
||||
@@ -53,6 +59,7 @@ export const MainContent = () => {
|
||||
staticAreaMaxItemHeight,
|
||||
availableTerminalHeight,
|
||||
cleanUiDetailsVisible,
|
||||
mouseMode,
|
||||
} = uiState;
|
||||
const showHeaderDetails = cleanUiDetailsVisible;
|
||||
|
||||
@@ -284,24 +291,63 @@ export const MainContent = () => {
|
||||
],
|
||||
);
|
||||
|
||||
const estimatedItemHeight = useCallback(() => 100, []);
|
||||
|
||||
const keyExtractor = useCallback(
|
||||
(item: (typeof virtualizedData)[number], _index: number) => {
|
||||
if (item.type === 'header') return 'header';
|
||||
if (item.type === 'history') return item.item.id.toString();
|
||||
return 'pending';
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const isStaticItem = useCallback(
|
||||
(item: (typeof virtualizedData)[number]) => item.type !== 'pending',
|
||||
[],
|
||||
);
|
||||
|
||||
const scrollableList = useMemo(() => {
|
||||
if (isAlternateBuffer) {
|
||||
return (
|
||||
<ScrollableList
|
||||
ref={scrollableListRef}
|
||||
hasFocus={
|
||||
!uiState.isEditorDialogOpen && !uiState.embeddedShellFocused
|
||||
}
|
||||
width={uiState.terminalWidth}
|
||||
data={virtualizedData}
|
||||
renderItem={renderItem}
|
||||
estimatedItemHeight={estimatedItemHeight}
|
||||
keyExtractor={keyExtractor}
|
||||
initialScrollIndex={SCROLL_TO_ITEM_END}
|
||||
initialScrollOffsetInIndex={SCROLL_TO_ITEM_END}
|
||||
renderStatic={useTerminalBuffer}
|
||||
isStaticItem={useTerminalBuffer ? isStaticItem : undefined}
|
||||
overflowToBackbuffer={useTerminalBuffer}
|
||||
scrollbar={mouseMode}
|
||||
/>
|
||||
// TODO(jacobr): consider adding stableScrollback={!config.getUseAlternateBuffer()}
|
||||
// but need to work out ensuring we only attempt it within a smaller range of scrollback vals.
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}, [
|
||||
isAlternateBuffer,
|
||||
uiState.isEditorDialogOpen,
|
||||
uiState.embeddedShellFocused,
|
||||
uiState.terminalWidth,
|
||||
virtualizedData,
|
||||
renderItem,
|
||||
estimatedItemHeight,
|
||||
keyExtractor,
|
||||
useTerminalBuffer,
|
||||
isStaticItem,
|
||||
mouseMode,
|
||||
]);
|
||||
|
||||
if (isAlternateBuffer) {
|
||||
return (
|
||||
<ScrollableList
|
||||
ref={scrollableListRef}
|
||||
hasFocus={!uiState.isEditorDialogOpen && !uiState.embeddedShellFocused}
|
||||
width={uiState.terminalWidth}
|
||||
data={virtualizedData}
|
||||
renderItem={renderItem}
|
||||
estimatedItemHeight={() => 100}
|
||||
keyExtractor={(item, _index) => {
|
||||
if (item.type === 'header') return 'header';
|
||||
if (item.type === 'history') return item.item.id.toString();
|
||||
return 'pending';
|
||||
}}
|
||||
initialScrollIndex={SCROLL_TO_ITEM_END}
|
||||
initialScrollOffsetInIndex={SCROLL_TO_ITEM_END}
|
||||
/>
|
||||
);
|
||||
return scrollableList;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user