mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-16 17:11:04 -07:00
fix: resolve infinite loop when using 'Modify with external editor' (#17453)
Co-authored-by: Jack Wotherspoon <jackwoth@google.com> Co-authored-by: ehedlund <ehedlund@google.com>
This commit is contained in:
@@ -525,12 +525,22 @@ export const AppContainer = (props: AppContainerProps) => {
|
||||
refreshStatic();
|
||||
}, [refreshStatic, isAlternateBuffer, app, config]);
|
||||
|
||||
const [editorError, setEditorError] = useState<string | null>(null);
|
||||
const {
|
||||
isEditorDialogOpen,
|
||||
openEditorDialog,
|
||||
handleEditorSelect,
|
||||
exitEditorDialog,
|
||||
} = useEditorSettings(settings, setEditorError, historyManager.addItem);
|
||||
|
||||
useEffect(() => {
|
||||
coreEvents.on(CoreEvent.ExternalEditorClosed, handleEditorClose);
|
||||
coreEvents.on(CoreEvent.RequestEditorSelection, openEditorDialog);
|
||||
return () => {
|
||||
coreEvents.off(CoreEvent.ExternalEditorClosed, handleEditorClose);
|
||||
coreEvents.off(CoreEvent.RequestEditorSelection, openEditorDialog);
|
||||
};
|
||||
}, [handleEditorClose]);
|
||||
}, [handleEditorClose, openEditorDialog]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
@@ -544,6 +554,9 @@ export const AppContainer = (props: AppContainerProps) => {
|
||||
}
|
||||
}, [bannerVisible, bannerText, settings, config, refreshStatic]);
|
||||
|
||||
const { isSettingsDialogOpen, openSettingsDialog, closeSettingsDialog } =
|
||||
useSettingsCommand();
|
||||
|
||||
const {
|
||||
isThemeDialogOpen,
|
||||
openThemeDialog,
|
||||
@@ -739,17 +752,6 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
onAuthError,
|
||||
]);
|
||||
|
||||
const [editorError, setEditorError] = useState<string | null>(null);
|
||||
const {
|
||||
isEditorDialogOpen,
|
||||
openEditorDialog,
|
||||
handleEditorSelect,
|
||||
exitEditorDialog,
|
||||
} = useEditorSettings(settings, setEditorError, historyManager.addItem);
|
||||
|
||||
const { isSettingsDialogOpen, openSettingsDialog, closeSettingsDialog } =
|
||||
useSettingsCommand();
|
||||
|
||||
const { isModelDialogOpen, openModelDialog, closeModelDialog } =
|
||||
useModelCommand();
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import {
|
||||
allowEditorTypeInSandbox,
|
||||
checkHasEditorType,
|
||||
hasValidEditorCommand,
|
||||
type EditorType,
|
||||
EDITOR_DISPLAY_NAMES,
|
||||
} from '@google/gemini-cli-core';
|
||||
@@ -31,7 +31,7 @@ class EditorSettingsManager {
|
||||
disabled: false,
|
||||
},
|
||||
...editorTypes.map((type) => {
|
||||
const hasEditor = checkHasEditorType(type);
|
||||
const hasEditor = hasValidEditorCommand(type);
|
||||
const isAllowedInSandbox = allowEditorTypeInSandbox(type);
|
||||
|
||||
let labelSuffix = !isAllowedInSandbox
|
||||
|
||||
@@ -24,7 +24,7 @@ import { SettingScope } from '../../config/settings.js';
|
||||
import { MessageType } from '../types.js';
|
||||
import {
|
||||
type EditorType,
|
||||
checkHasEditorType,
|
||||
hasValidEditorCommand,
|
||||
allowEditorTypeInSandbox,
|
||||
} from '@google/gemini-cli-core';
|
||||
import type { UseHistoryManagerReturn } from './useHistoryManager.js';
|
||||
@@ -35,12 +35,12 @@ vi.mock('@google/gemini-cli-core', async () => {
|
||||
const actual = await vi.importActual('@google/gemini-cli-core');
|
||||
return {
|
||||
...actual,
|
||||
checkHasEditorType: vi.fn(() => true),
|
||||
hasValidEditorCommand: vi.fn(() => true),
|
||||
allowEditorTypeInSandbox: vi.fn(() => true),
|
||||
};
|
||||
});
|
||||
|
||||
const mockCheckHasEditorType = vi.mocked(checkHasEditorType);
|
||||
const mockHasValidEditorCommand = vi.mocked(hasValidEditorCommand);
|
||||
const mockAllowEditorTypeInSandbox = vi.mocked(allowEditorTypeInSandbox);
|
||||
|
||||
describe('useEditorSettings', () => {
|
||||
@@ -69,7 +69,7 @@ describe('useEditorSettings', () => {
|
||||
mockAddItem = vi.fn();
|
||||
|
||||
// Reset mock implementations to default
|
||||
mockCheckHasEditorType.mockReturnValue(true);
|
||||
mockHasValidEditorCommand.mockReturnValue(true);
|
||||
mockAllowEditorTypeInSandbox.mockReturnValue(true);
|
||||
});
|
||||
|
||||
@@ -224,7 +224,7 @@ describe('useEditorSettings', () => {
|
||||
it('should not set preference for unavailable editors', () => {
|
||||
render(<TestComponent />);
|
||||
|
||||
mockCheckHasEditorType.mockReturnValue(false);
|
||||
mockHasValidEditorCommand.mockReturnValue(false);
|
||||
|
||||
const editorType: EditorType = 'vscode';
|
||||
const scope = SettingScope.User;
|
||||
|
||||
@@ -13,8 +13,10 @@ import { MessageType } from '../types.js';
|
||||
import type { EditorType } from '@google/gemini-cli-core';
|
||||
import {
|
||||
allowEditorTypeInSandbox,
|
||||
checkHasEditorType,
|
||||
hasValidEditorCommand,
|
||||
getEditorDisplayName,
|
||||
coreEvents,
|
||||
CoreEvent,
|
||||
} from '@google/gemini-cli-core';
|
||||
import type { UseHistoryManagerReturn } from './useHistoryManager.js';
|
||||
|
||||
@@ -45,7 +47,7 @@ export const useEditorSettings = (
|
||||
(editorType: EditorType | undefined, scope: LoadableSettingScope) => {
|
||||
if (
|
||||
editorType &&
|
||||
(!checkHasEditorType(editorType) ||
|
||||
(!hasValidEditorCommand(editorType) ||
|
||||
!allowEditorTypeInSandbox(editorType))
|
||||
) {
|
||||
return;
|
||||
@@ -66,6 +68,7 @@ export const useEditorSettings = (
|
||||
);
|
||||
setEditorError(null);
|
||||
setIsEditorDialogOpen(false);
|
||||
coreEvents.emit(CoreEvent.EditorSelected, { editor: editorType });
|
||||
} catch (error) {
|
||||
setEditorError(`Failed to set editor preference: ${error}`);
|
||||
}
|
||||
@@ -75,6 +78,7 @@ export const useEditorSettings = (
|
||||
|
||||
const exitEditorDialog = useCallback(() => {
|
||||
setIsEditorDialogOpen(false);
|
||||
coreEvents.emit(CoreEvent.EditorSelected, { editor: undefined });
|
||||
}, []);
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user