mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-24 20:14:44 -07:00
refactor(cli): code review cleanup fix for tab+tab (#18967)
This commit is contained in:
@@ -134,7 +134,6 @@ import { ShellFocusContext } from './contexts/ShellFocusContext.js';
|
||||
import { type ExtensionManager } from '../config/extension-manager.js';
|
||||
import { requestConsentInteractive } from '../config/extensions/consent.js';
|
||||
import { useSessionBrowser } from './hooks/useSessionBrowser.js';
|
||||
import { persistentState } from '../utils/persistentState.js';
|
||||
import { useSessionResume } from './hooks/useSessionResume.js';
|
||||
import { useIncludeDirsTrust } from './hooks/useIncludeDirsTrust.js';
|
||||
import { useSessionRetentionCheck } from './hooks/useSessionRetentionCheck.js';
|
||||
@@ -189,8 +188,11 @@ interface AppContainerProps {
|
||||
resumedSessionData?: ResumedSessionData;
|
||||
}
|
||||
|
||||
const APPROVAL_MODE_REVEAL_DURATION_MS = 1200;
|
||||
const FOCUS_UI_ENABLED_STATE_KEY = 'focusUiEnabled';
|
||||
import { useRepeatedKeyPress } from './hooks/useRepeatedKeyPress.js';
|
||||
import {
|
||||
useVisibilityToggle,
|
||||
APPROVAL_MODE_REVEAL_DURATION_MS,
|
||||
} from './hooks/useVisibilityToggle.js';
|
||||
|
||||
/**
|
||||
* The fraction of the terminal width to allocate to the shell.
|
||||
@@ -803,65 +805,14 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
const setIsBackgroundShellListOpenRef = useRef<(open: boolean) => void>(
|
||||
() => {},
|
||||
);
|
||||
const [focusUiEnabledByDefault] = useState(
|
||||
() => persistentState.get(FOCUS_UI_ENABLED_STATE_KEY) === true,
|
||||
);
|
||||
const [shortcutsHelpVisible, setShortcutsHelpVisible] = useState(false);
|
||||
const [cleanUiDetailsVisible, setCleanUiDetailsVisibleState] = useState(
|
||||
!focusUiEnabledByDefault,
|
||||
);
|
||||
const modeRevealTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const cleanUiDetailsPinnedRef = useRef(!focusUiEnabledByDefault);
|
||||
|
||||
const clearModeRevealTimeout = useCallback(() => {
|
||||
if (modeRevealTimeoutRef.current) {
|
||||
clearTimeout(modeRevealTimeoutRef.current);
|
||||
modeRevealTimeoutRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const persistFocusUiPreference = useCallback((isFullUiVisible: boolean) => {
|
||||
persistentState.set(FOCUS_UI_ENABLED_STATE_KEY, !isFullUiVisible);
|
||||
}, []);
|
||||
|
||||
const setCleanUiDetailsVisible = useCallback(
|
||||
(visible: boolean) => {
|
||||
clearModeRevealTimeout();
|
||||
cleanUiDetailsPinnedRef.current = visible;
|
||||
setCleanUiDetailsVisibleState(visible);
|
||||
persistFocusUiPreference(visible);
|
||||
},
|
||||
[clearModeRevealTimeout, persistFocusUiPreference],
|
||||
);
|
||||
|
||||
const toggleCleanUiDetailsVisible = useCallback(() => {
|
||||
clearModeRevealTimeout();
|
||||
setCleanUiDetailsVisibleState((visible) => {
|
||||
const nextVisible = !visible;
|
||||
cleanUiDetailsPinnedRef.current = nextVisible;
|
||||
persistFocusUiPreference(nextVisible);
|
||||
return nextVisible;
|
||||
});
|
||||
}, [clearModeRevealTimeout, persistFocusUiPreference]);
|
||||
|
||||
const revealCleanUiDetailsTemporarily = useCallback(
|
||||
(durationMs: number = APPROVAL_MODE_REVEAL_DURATION_MS) => {
|
||||
if (cleanUiDetailsPinnedRef.current) {
|
||||
return;
|
||||
}
|
||||
clearModeRevealTimeout();
|
||||
setCleanUiDetailsVisibleState(true);
|
||||
modeRevealTimeoutRef.current = setTimeout(() => {
|
||||
if (!cleanUiDetailsPinnedRef.current) {
|
||||
setCleanUiDetailsVisibleState(false);
|
||||
}
|
||||
modeRevealTimeoutRef.current = null;
|
||||
}, durationMs);
|
||||
},
|
||||
[clearModeRevealTimeout],
|
||||
);
|
||||
|
||||
useEffect(() => () => clearModeRevealTimeout(), [clearModeRevealTimeout]);
|
||||
const {
|
||||
cleanUiDetailsVisible,
|
||||
setCleanUiDetailsVisible,
|
||||
toggleCleanUiDetailsVisible,
|
||||
revealCleanUiDetailsTemporarily,
|
||||
} = useVisibilityToggle();
|
||||
|
||||
const slashCommandActions = useMemo(
|
||||
() => ({
|
||||
@@ -1396,10 +1347,29 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
const [showFullTodos, setShowFullTodos] = useState<boolean>(false);
|
||||
const [renderMarkdown, setRenderMarkdown] = useState<boolean>(true);
|
||||
|
||||
const [ctrlCPressCount, setCtrlCPressCount] = useState(0);
|
||||
const ctrlCTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const [ctrlDPressCount, setCtrlDPressCount] = useState(0);
|
||||
const ctrlDTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
const handleExitRepeat = useCallback(
|
||||
(count: number) => {
|
||||
if (count > 2) {
|
||||
recordExitFail(config);
|
||||
}
|
||||
if (count > 1) {
|
||||
void handleSlashCommand('/quit', undefined, undefined, false);
|
||||
}
|
||||
},
|
||||
[config, handleSlashCommand],
|
||||
);
|
||||
|
||||
const { pressCount: ctrlCPressCount, handlePress: handleCtrlCPress } =
|
||||
useRepeatedKeyPress({
|
||||
windowMs: WARNING_PROMPT_DURATION_MS,
|
||||
onRepeat: handleExitRepeat,
|
||||
});
|
||||
|
||||
const { pressCount: ctrlDPressCount, handlePress: handleCtrlDPress } =
|
||||
useRepeatedKeyPress({
|
||||
windowMs: WARNING_PROMPT_DURATION_MS,
|
||||
onRepeat: handleExitRepeat,
|
||||
});
|
||||
const [constrainHeight, setConstrainHeight] = useState<boolean>(true);
|
||||
const [ideContextState, setIdeContextState] = useState<
|
||||
IdeContext | undefined
|
||||
@@ -1478,9 +1448,6 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
if (tabFocusTimeoutRef.current) {
|
||||
clearTimeout(tabFocusTimeoutRef.current);
|
||||
}
|
||||
if (modeRevealTimeoutRef.current) {
|
||||
clearTimeout(modeRevealTimeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, [showTransientMessage]);
|
||||
|
||||
@@ -1553,44 +1520,6 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
};
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ctrlCTimerRef.current) {
|
||||
clearTimeout(ctrlCTimerRef.current);
|
||||
ctrlCTimerRef.current = null;
|
||||
}
|
||||
if (ctrlCPressCount > 2) {
|
||||
recordExitFail(config);
|
||||
}
|
||||
if (ctrlCPressCount > 1) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
handleSlashCommand('/quit', undefined, undefined, false);
|
||||
} else if (ctrlCPressCount > 0) {
|
||||
ctrlCTimerRef.current = setTimeout(() => {
|
||||
setCtrlCPressCount(0);
|
||||
ctrlCTimerRef.current = null;
|
||||
}, WARNING_PROMPT_DURATION_MS);
|
||||
}
|
||||
}, [ctrlCPressCount, config, setCtrlCPressCount, handleSlashCommand]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ctrlDTimerRef.current) {
|
||||
clearTimeout(ctrlDTimerRef.current);
|
||||
ctrlCTimerRef.current = null;
|
||||
}
|
||||
if (ctrlDPressCount > 2) {
|
||||
recordExitFail(config);
|
||||
}
|
||||
if (ctrlDPressCount > 1) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
handleSlashCommand('/quit', undefined, undefined, false);
|
||||
} else if (ctrlDPressCount > 0) {
|
||||
ctrlDTimerRef.current = setTimeout(() => {
|
||||
setCtrlDPressCount(0);
|
||||
ctrlDTimerRef.current = null;
|
||||
}, WARNING_PROMPT_DURATION_MS);
|
||||
}
|
||||
}, [ctrlDPressCount, config, setCtrlDPressCount, handleSlashCommand]);
|
||||
|
||||
const handleEscapePromptChange = useCallback((showPrompt: boolean) => {
|
||||
setShowEscapePrompt(showPrompt);
|
||||
}, []);
|
||||
@@ -1637,10 +1566,10 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
// This should happen regardless of the count.
|
||||
cancelOngoingRequest?.();
|
||||
|
||||
setCtrlCPressCount((prev) => prev + 1);
|
||||
handleCtrlCPress();
|
||||
return true;
|
||||
} else if (keyMatchers[Command.EXIT](key)) {
|
||||
setCtrlDPressCount((prev) => prev + 1);
|
||||
handleCtrlDPress();
|
||||
return true;
|
||||
} else if (keyMatchers[Command.SUSPEND_APP](key)) {
|
||||
handleSuspend();
|
||||
@@ -1781,8 +1710,8 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
setShowErrorDetails,
|
||||
config,
|
||||
ideContextState,
|
||||
setCtrlCPressCount,
|
||||
setCtrlDPressCount,
|
||||
handleCtrlCPress,
|
||||
handleCtrlDPress,
|
||||
handleSlashCommand,
|
||||
cancelOngoingRequest,
|
||||
activePtyId,
|
||||
|
||||
Reference in New Issue
Block a user