mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-18 17:20:38 -07:00
feat(ui): Introduce useUI Hook and UIContext (#5488)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
22
packages/cli/src/ui/contexts/AppContext.tsx
Normal file
22
packages/cli/src/ui/contexts/AppContext.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
export interface AppState {
|
||||
version: string;
|
||||
startupWarnings: string[];
|
||||
}
|
||||
|
||||
export const AppContext = createContext<AppState | null>(null);
|
||||
|
||||
export const useAppContext = () => {
|
||||
const context = useContext(AppContext);
|
||||
if (!context) {
|
||||
throw new Error('useAppContext must be used within an AppProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
18
packages/cli/src/ui/contexts/ConfigContext.tsx
Normal file
18
packages/cli/src/ui/contexts/ConfigContext.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import React, { useContext } from 'react';
|
||||
import { type Config } from '@google/gemini-cli-core';
|
||||
|
||||
export const ConfigContext = React.createContext<Config | undefined>(undefined);
|
||||
|
||||
export const useConfig = () => {
|
||||
const context = useContext(ConfigContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useConfig must be used within a ConfigProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
56
packages/cli/src/ui/contexts/UIActionsContext.tsx
Normal file
56
packages/cli/src/ui/contexts/UIActionsContext.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { createContext, useContext } from 'react';
|
||||
import { type Key } from '../hooks/useKeypress.js';
|
||||
import { type IdeIntegrationNudgeResult } from '../IdeIntegrationNudge.js';
|
||||
import { type FolderTrustChoice } from '../components/FolderTrustDialog.js';
|
||||
import { type AuthType, type EditorType } from '@google/gemini-cli-core';
|
||||
import { type SettingScope } from '../../config/settings.js';
|
||||
import type { AuthState } from '../types.js';
|
||||
|
||||
export interface UIActions {
|
||||
handleThemeSelect: (
|
||||
themeName: string | undefined,
|
||||
scope: SettingScope,
|
||||
) => void;
|
||||
handleThemeHighlight: (themeName: string | undefined) => void;
|
||||
handleAuthSelect: (
|
||||
authType: AuthType | undefined,
|
||||
scope: SettingScope,
|
||||
) => void;
|
||||
setAuthState: (state: AuthState) => void;
|
||||
onAuthError: (error: string) => void;
|
||||
handleEditorSelect: (
|
||||
editorType: EditorType | undefined,
|
||||
scope: SettingScope,
|
||||
) => void;
|
||||
exitEditorDialog: () => void;
|
||||
exitPrivacyNotice: () => void;
|
||||
closeSettingsDialog: () => void;
|
||||
setShellModeActive: (value: boolean) => void;
|
||||
vimHandleInput: (key: Key) => boolean;
|
||||
handleIdePromptComplete: (result: IdeIntegrationNudgeResult) => void;
|
||||
handleFolderTrustSelect: (choice: FolderTrustChoice) => void;
|
||||
setConstrainHeight: (value: boolean) => void;
|
||||
onEscapePromptChange: (show: boolean) => void;
|
||||
refreshStatic: () => void;
|
||||
handleFinalSubmit: (value: string) => void;
|
||||
handleClearScreen: () => void;
|
||||
onWorkspaceMigrationDialogOpen: () => void;
|
||||
onWorkspaceMigrationDialogClose: () => void;
|
||||
handleProQuotaChoice: (choice: 'auth' | 'continue') => void;
|
||||
}
|
||||
|
||||
export const UIActionsContext = createContext<UIActions | null>(null);
|
||||
|
||||
export const useUIActions = () => {
|
||||
const context = useContext(UIActionsContext);
|
||||
if (!context) {
|
||||
throw new Error('useUIActions must be used within a UIActionsProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
112
packages/cli/src/ui/contexts/UIStateContext.tsx
Normal file
112
packages/cli/src/ui/contexts/UIStateContext.tsx
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { createContext, useContext } from 'react';
|
||||
import type {
|
||||
HistoryItem,
|
||||
ThoughtSummary,
|
||||
ConsoleMessageItem,
|
||||
ShellConfirmationRequest,
|
||||
ConfirmationRequest,
|
||||
HistoryItemWithoutId,
|
||||
StreamingState,
|
||||
} from '../types.js';
|
||||
import type { CommandContext, SlashCommand } from '../commands/types.js';
|
||||
import type { TextBuffer } from '../components/shared/text-buffer.js';
|
||||
import type {
|
||||
IdeContext,
|
||||
ApprovalMode,
|
||||
UserTierId,
|
||||
DetectedIde,
|
||||
} from '@google/gemini-cli-core';
|
||||
import type { DOMElement } from 'ink';
|
||||
import type { SessionStatsState } from '../contexts/SessionContext.js';
|
||||
import type { UpdateObject } from '../utils/updateCheck.js';
|
||||
|
||||
export interface UIState {
|
||||
history: HistoryItem[];
|
||||
isThemeDialogOpen: boolean;
|
||||
themeError: string | null;
|
||||
isAuthenticating: boolean;
|
||||
authError: string | null;
|
||||
isAuthDialogOpen: boolean;
|
||||
editorError: string | null;
|
||||
isEditorDialogOpen: boolean;
|
||||
showPrivacyNotice: boolean;
|
||||
corgiMode: boolean;
|
||||
debugMessage: string;
|
||||
quittingMessages: HistoryItem[] | null;
|
||||
isSettingsDialogOpen: boolean;
|
||||
slashCommands: readonly SlashCommand[];
|
||||
pendingSlashCommandHistoryItems: HistoryItemWithoutId[];
|
||||
commandContext: CommandContext;
|
||||
shellConfirmationRequest: ShellConfirmationRequest | null;
|
||||
confirmationRequest: ConfirmationRequest | null;
|
||||
geminiMdFileCount: number;
|
||||
streamingState: StreamingState;
|
||||
initError: string | null;
|
||||
pendingGeminiHistoryItems: HistoryItemWithoutId[];
|
||||
thought: ThoughtSummary | null;
|
||||
shellModeActive: boolean;
|
||||
userMessages: string[];
|
||||
buffer: TextBuffer;
|
||||
inputWidth: number;
|
||||
suggestionsWidth: number;
|
||||
isInputActive: boolean;
|
||||
shouldShowIdePrompt: boolean;
|
||||
isFolderTrustDialogOpen: boolean;
|
||||
isTrustedFolder: boolean | undefined;
|
||||
constrainHeight: boolean;
|
||||
showErrorDetails: boolean;
|
||||
filteredConsoleMessages: ConsoleMessageItem[];
|
||||
ideContextState: IdeContext | undefined;
|
||||
showToolDescriptions: boolean;
|
||||
ctrlCPressedOnce: boolean;
|
||||
ctrlDPressedOnce: boolean;
|
||||
showEscapePrompt: boolean;
|
||||
isFocused: boolean;
|
||||
elapsedTime: number;
|
||||
currentLoadingPhrase: string;
|
||||
historyRemountKey: number;
|
||||
messageQueue: string[];
|
||||
showAutoAcceptIndicator: ApprovalMode;
|
||||
showWorkspaceMigrationDialog: boolean;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
workspaceExtensions: any[]; // Extension[]
|
||||
// Quota-related state
|
||||
userTier: UserTierId | undefined;
|
||||
isProQuotaDialogOpen: boolean;
|
||||
currentModel: string;
|
||||
// New fields for complete state management
|
||||
contextFileNames: string[];
|
||||
errorCount: number;
|
||||
availableTerminalHeight: number | undefined;
|
||||
mainAreaWidth: number;
|
||||
staticAreaMaxItemHeight: number;
|
||||
staticExtraHeight: number;
|
||||
dialogsVisible: boolean;
|
||||
pendingHistoryItems: HistoryItemWithoutId[];
|
||||
nightly: boolean;
|
||||
branchName: string | undefined;
|
||||
sessionStats: SessionStatsState;
|
||||
terminalWidth: number;
|
||||
terminalHeight: number;
|
||||
mainControlsRef: React.MutableRefObject<DOMElement | null>;
|
||||
currentIDE: DetectedIde | null;
|
||||
updateInfo: UpdateObject | null;
|
||||
showIdeRestartPrompt: boolean;
|
||||
isRestarting: boolean;
|
||||
}
|
||||
|
||||
export const UIStateContext = createContext<UIState | null>(null);
|
||||
|
||||
export const useUIState = () => {
|
||||
const context = useContext(UIStateContext);
|
||||
if (!context) {
|
||||
throw new Error('useUIState must be used within a UIStateProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
Reference in New Issue
Block a user