Increase paste timeout + add warning. (#13099)

This commit is contained in:
Tommaso Sciortino
2025-11-14 16:02:28 -08:00
committed by GitHub
parent ab6b2293e1
commit d03496b710
5 changed files with 29 additions and 13 deletions

View File

@@ -898,7 +898,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
>(); >();
const [showEscapePrompt, setShowEscapePrompt] = useState(false); const [showEscapePrompt, setShowEscapePrompt] = useState(false);
const [showIdeRestartPrompt, setShowIdeRestartPrompt] = useState(false); const [showIdeRestartPrompt, setShowIdeRestartPrompt] = useState(false);
const [selectionWarning, setSelectionWarning] = useState(false); const [warningMessage, setWarningMessage] = useState<string | null>(null);
const { isFolderTrustDialogOpen, handleFolderTrustSelect, isRestarting } = const { isFolderTrustDialogOpen, handleFolderTrustSelect, isRestarting } =
useFolderTrust(settings, setIsTrustedFolder, historyManager.addItem); useFolderTrust(settings, setIsTrustedFolder, historyManager.addItem);
@@ -910,18 +910,28 @@ Logging in with Google... Please restart Gemini CLI to continue.
useEffect(() => { useEffect(() => {
let timeoutId: NodeJS.Timeout; let timeoutId: NodeJS.Timeout;
const handleSelectionWarning = () => {
setSelectionWarning(true); const handleWarning = (message: string) => {
setWarningMessage(message);
if (timeoutId) { if (timeoutId) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
} }
timeoutId = setTimeout(() => { timeoutId = setTimeout(() => {
setSelectionWarning(false); setWarningMessage(null);
}, WARNING_PROMPT_DURATION_MS); }, WARNING_PROMPT_DURATION_MS);
}; };
const handleSelectionWarning = () => {
handleWarning('Press Ctrl-S to enter selection mode to copy text.');
};
const handlePasteTimeout = () => {
handleWarning('Paste Timed out. Possibly due to slow connection.');
};
appEvents.on(AppEvent.SelectionWarning, handleSelectionWarning); appEvents.on(AppEvent.SelectionWarning, handleSelectionWarning);
appEvents.on(AppEvent.PasteTimeout, handlePasteTimeout);
return () => { return () => {
appEvents.off(AppEvent.SelectionWarning, handleSelectionWarning); appEvents.off(AppEvent.SelectionWarning, handleSelectionWarning);
appEvents.off(AppEvent.PasteTimeout, handlePasteTimeout);
if (timeoutId) { if (timeoutId) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
} }
@@ -1373,7 +1383,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
embeddedShellFocused, embeddedShellFocused,
showDebugProfiler, showDebugProfiler,
copyModeEnabled, copyModeEnabled,
selectionWarning, warningMessage,
}), }),
[ [
isThemeDialogOpen, isThemeDialogOpen,
@@ -1460,7 +1470,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
apiKeyDefaultValue, apiKeyDefaultValue,
authState, authState,
copyModeEnabled, copyModeEnabled,
selectionWarning, warningMessage,
], ],
); );

View File

@@ -99,10 +99,8 @@ export const Composer = () => {
<Text color={theme.status.warning}> <Text color={theme.status.warning}>
Press Ctrl+C again to exit. Press Ctrl+C again to exit.
</Text> </Text>
) : uiState.selectionWarning ? ( ) : uiState.warningMessage ? (
<Text color={theme.status.warning}> <Text color={theme.status.warning}>{uiState.warningMessage}</Text>
Press Ctrl-S to enter selection mode to copy text.
</Text>
) : uiState.ctrlDPressedOnce ? ( ) : uiState.ctrlDPressedOnce ? (
<Text color={theme.status.warning}> <Text color={theme.status.warning}>
Press Ctrl+D again to exit. Press Ctrl+D again to exit.

View File

@@ -18,10 +18,11 @@ import {
import { ESC } from '../utils/input.js'; import { ESC } from '../utils/input.js';
import { parseMouseEvent } from '../utils/mouse.js'; import { parseMouseEvent } from '../utils/mouse.js';
import { FOCUS_IN, FOCUS_OUT } from '../hooks/useFocus.js'; import { FOCUS_IN, FOCUS_OUT } from '../hooks/useFocus.js';
import { appEvents, AppEvent } from '../../utils/events.js';
export const BACKSLASH_ENTER_TIMEOUT = 5; export const BACKSLASH_ENTER_TIMEOUT = 5;
export const ESC_TIMEOUT = 50; export const ESC_TIMEOUT = 50;
export const PASTE_TIMEOUT = 50; export const PASTE_TIMEOUT = 30_000;
// Parse the key itself // Parse the key itself
const KEY_INFO_MAP: Record< const KEY_INFO_MAP: Record<
@@ -211,7 +212,12 @@ function bufferPaste(
key = yield; key = yield;
clearTimeout(timeoutId); clearTimeout(timeoutId);
if (key === null || key.name === 'paste-end') { if (key === null) {
appEvents.emit(AppEvent.PasteTimeout);
break;
}
if (key.name === 'paste-end') {
break; break;
} }
buffer += key.sequence; buffer += key.sequence;

View File

@@ -125,7 +125,7 @@ export interface UIState {
showDebugProfiler: boolean; showDebugProfiler: boolean;
showFullTodos: boolean; showFullTodos: boolean;
copyModeEnabled: boolean; copyModeEnabled: boolean;
selectionWarning: boolean; warningMessage: string | null;
} }
export const UIStateContext = createContext<UIState | null>(null); export const UIStateContext = createContext<UIState | null>(null);

View File

@@ -14,6 +14,7 @@ export enum AppEvent {
Flicker = 'flicker', Flicker = 'flicker',
McpClientUpdate = 'mcp-client-update', McpClientUpdate = 'mcp-client-update',
SelectionWarning = 'selection-warning', SelectionWarning = 'selection-warning',
PasteTimeout = 'paste-timeout',
} }
export interface AppEvents extends ExtensionEvents { export interface AppEvents extends ExtensionEvents {
@@ -23,6 +24,7 @@ export interface AppEvents extends ExtensionEvents {
[AppEvent.Flicker]: never[]; [AppEvent.Flicker]: never[];
[AppEvent.McpClientUpdate]: Array<Map<string, McpClient> | never>; [AppEvent.McpClientUpdate]: Array<Map<string, McpClient> | never>;
[AppEvent.SelectionWarning]: never[]; [AppEvent.SelectionWarning]: never[];
[AppEvent.PasteTimeout]: never[];
} }
export const appEvents = new EventEmitter<AppEvents>(); export const appEvents = new EventEmitter<AppEvents>();