mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-15 08:31:14 -07:00
Speculative fixes to try to fix react error. (#19508)
This commit is contained in:
@@ -80,20 +80,24 @@ export function useFocusHint(
|
|||||||
isThisShellFocused: boolean,
|
isThisShellFocused: boolean,
|
||||||
resultDisplay: ToolResultDisplay | undefined,
|
resultDisplay: ToolResultDisplay | undefined,
|
||||||
) {
|
) {
|
||||||
const [lastUpdateTime, setLastUpdateTime] = useState<Date | null>(null);
|
|
||||||
const [userHasFocused, setUserHasFocused] = useState(false);
|
const [userHasFocused, setUserHasFocused] = useState(false);
|
||||||
|
|
||||||
|
// Derive a stable reset key for the inactivity timer. For strings and arrays
|
||||||
|
// (shell output), we use the length to capture updates without referential
|
||||||
|
// identity issues or expensive deep comparisons.
|
||||||
|
const resetKey =
|
||||||
|
typeof resultDisplay === 'string'
|
||||||
|
? resultDisplay.length
|
||||||
|
: Array.isArray(resultDisplay)
|
||||||
|
? resultDisplay.length
|
||||||
|
: !!resultDisplay;
|
||||||
|
|
||||||
const showFocusHint = useInactivityTimer(
|
const showFocusHint = useInactivityTimer(
|
||||||
isThisShellFocusable,
|
isThisShellFocusable,
|
||||||
lastUpdateTime ? lastUpdateTime.getTime() : 0,
|
resetKey,
|
||||||
SHELL_FOCUS_HINT_DELAY_MS,
|
SHELL_FOCUS_HINT_DELAY_MS,
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (resultDisplay) {
|
|
||||||
setLastUpdateTime(new Date());
|
|
||||||
}
|
|
||||||
}, [resultDisplay]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isThisShellFocused) {
|
if (isThisShellFocused) {
|
||||||
setUserHasFocused(true);
|
setUserHasFocused(true);
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ describe('useConsoleMessages', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
await vi.advanceTimersByTimeAsync(20);
|
await vi.advanceTimersByTimeAsync(60);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.current.consoleMessages).toEqual([
|
expect(result.current.consoleMessages).toEqual([
|
||||||
@@ -114,7 +114,7 @@ describe('useConsoleMessages', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
await vi.advanceTimersByTimeAsync(20);
|
await vi.advanceTimersByTimeAsync(60);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.current.consoleMessages).toEqual([
|
expect(result.current.consoleMessages).toEqual([
|
||||||
@@ -131,7 +131,7 @@ describe('useConsoleMessages', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
await vi.advanceTimersByTimeAsync(20);
|
await vi.advanceTimersByTimeAsync(60);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.current.consoleMessages).toEqual([
|
expect(result.current.consoleMessages).toEqual([
|
||||||
@@ -148,7 +148,7 @@ describe('useConsoleMessages', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
await vi.advanceTimersByTimeAsync(20);
|
await vi.advanceTimersByTimeAsync(60);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result.current.consoleMessages).toHaveLength(1);
|
expect(result.current.consoleMessages).toHaveLength(1);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useReducer,
|
useReducer,
|
||||||
useRef,
|
useRef,
|
||||||
useTransition,
|
startTransition,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import type { ConsoleMessageItem } from '../types.js';
|
import type { ConsoleMessageItem } from '../types.js';
|
||||||
import {
|
import {
|
||||||
@@ -71,10 +71,11 @@ export function useConsoleMessages(): UseConsoleMessagesReturn {
|
|||||||
const [consoleMessages, dispatch] = useReducer(consoleMessagesReducer, []);
|
const [consoleMessages, dispatch] = useReducer(consoleMessagesReducer, []);
|
||||||
const messageQueueRef = useRef<ConsoleMessageItem[]>([]);
|
const messageQueueRef = useRef<ConsoleMessageItem[]>([]);
|
||||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const [, startTransition] = useTransition();
|
const isProcessingRef = useRef(false);
|
||||||
|
|
||||||
const processQueue = useCallback(() => {
|
const processQueue = useCallback(() => {
|
||||||
if (messageQueueRef.current.length > 0) {
|
if (messageQueueRef.current.length > 0) {
|
||||||
|
isProcessingRef.current = true;
|
||||||
const messagesToProcess = messageQueueRef.current;
|
const messagesToProcess = messageQueueRef.current;
|
||||||
messageQueueRef.current = [];
|
messageQueueRef.current = [];
|
||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
@@ -87,15 +88,26 @@ export function useConsoleMessages(): UseConsoleMessagesReturn {
|
|||||||
const handleNewMessage = useCallback(
|
const handleNewMessage = useCallback(
|
||||||
(message: ConsoleMessageItem) => {
|
(message: ConsoleMessageItem) => {
|
||||||
messageQueueRef.current.push(message);
|
messageQueueRef.current.push(message);
|
||||||
if (!timeoutRef.current) {
|
if (!isProcessingRef.current && !timeoutRef.current) {
|
||||||
// Batch updates using a timeout. 16ms is a reasonable delay to batch
|
// Batch updates using a timeout. 50ms is a reasonable delay to batch
|
||||||
// rapid-fire messages without noticeable lag.
|
// rapid-fire messages without noticeable lag while avoiding React update
|
||||||
timeoutRef.current = setTimeout(processQueue, 16);
|
// queue flooding.
|
||||||
|
timeoutRef.current = setTimeout(processQueue, 50);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[processQueue],
|
[processQueue],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Once the updated consoleMessages have been committed to the screen,
|
||||||
|
// we can safely process the next batch of queued messages if any exist.
|
||||||
|
// This completely eliminates overlapping concurrent updates to this state.
|
||||||
|
useEffect(() => {
|
||||||
|
isProcessingRef.current = false;
|
||||||
|
if (messageQueueRef.current.length > 0 && !timeoutRef.current) {
|
||||||
|
timeoutRef.current = setTimeout(processQueue, 50);
|
||||||
|
}
|
||||||
|
}, [consoleMessages, processQueue]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleConsoleLog = (payload: ConsoleLogPayload) => {
|
const handleConsoleLog = (payload: ConsoleLogPayload) => {
|
||||||
let content = payload.content;
|
let content = payload.content;
|
||||||
@@ -149,6 +161,7 @@ export function useConsoleMessages(): UseConsoleMessagesReturn {
|
|||||||
timeoutRef.current = null;
|
timeoutRef.current = null;
|
||||||
}
|
}
|
||||||
messageQueueRef.current = [];
|
messageQueueRef.current = [];
|
||||||
|
isProcessingRef.current = true;
|
||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
dispatch({ type: 'CLEAR' });
|
dispatch({ type: 'CLEAR' });
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user