feat(ui): Introduce useUI Hook and UIContext (#5488)

Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
Keith Lyons
2025-09-06 01:39:02 -04:00
committed by GitHub
parent fe15b04f33
commit 885af07ddb
40 changed files with 3443 additions and 3388 deletions
+52 -12
View File
@@ -7,7 +7,7 @@
import React, { useState, useEffect } from 'react';
import { render, Box, Text } from 'ink';
import Spinner from 'ink-spinner';
import { AppWrapper } from './ui/App.js';
import { AppContainer } from './ui/AppContainer.js';
import { loadCliConfig, parseArguments } from './config/config.js';
import { readStdin } from './utils/readStdin.js';
import { basename } from 'node:path';
@@ -38,6 +38,10 @@ import {
getOauthClient,
uiTelemetryService,
} from '@google/gemini-cli-core';
import {
initializeApp,
type InitializationResult,
} from './core/initializer.js';
import { validateAuthMethod } from './config/auth.js';
import { setMaxSizedBoxDebugging } from './ui/components/shared/MaxSizedBox.js';
import { validateNonInteractiveAuth } from './validateNonInterActiveAuth.js';
@@ -47,6 +51,10 @@ import { handleAutoUpdate } from './utils/handleAutoUpdate.js';
import { appEvents, AppEvent } from './utils/events.js';
import { SettingsContext } from './ui/contexts/SettingsContext.js';
import { writeFileSync } from 'node:fs';
import { SessionStatsProvider } from './ui/contexts/SessionContext.js';
import { VimModeProvider } from './ui/contexts/VimModeContext.js';
import { KeypressProvider } from './ui/contexts/KeypressContext.js';
import { useKittyKeyboardProtocol } from './ui/hooks/useKittyKeyboardProtocol.js';
export function validateDnsResolutionOrder(
order: string | undefined,
@@ -170,21 +178,45 @@ export async function startInteractiveUI(
settings: LoadedSettings,
startupWarnings: string[],
workspaceRoot: string = process.cwd(),
initializationResult: InitializationResult,
) {
const version = await getCliVersion();
setWindowTitle(basename(workspaceRoot), settings);
// Create wrapper component to use hooks inside render
const AppWrapper = () => {
const kittyProtocolStatus = useKittyKeyboardProtocol();
return (
<SettingsContext.Provider value={settings}>
<KeypressProvider
kittyProtocolEnabled={kittyProtocolStatus.enabled}
config={config}
debugKeystrokeLogging={settings.merged.general?.debugKeystrokeLogging}
>
<SessionStatsProvider>
<VimModeProvider settings={settings}>
<AppContainer
config={config}
settings={settings}
startupWarnings={startupWarnings}
version={version}
initializationResult={initializationResult}
/>
</VimModeProvider>
</SessionStatsProvider>
</KeypressProvider>
</SettingsContext.Provider>
);
};
const instance = render(
<React.StrictMode>
<SettingsContext.Provider value={settings}>
<AppWrapper
config={config}
settings={settings}
startupWarnings={startupWarnings}
version={version}
/>
</SettingsContext.Provider>
<AppWrapper />
</React.StrictMode>,
{ exitOnCtrlC: false, isScreenReaderEnabled: config.getScreenReader() },
{
exitOnCtrlC: false,
isScreenReaderEnabled: config.getScreenReader(),
},
);
checkForUpdates()
@@ -308,11 +340,13 @@ export async function main() {
if (settings.merged.ui?.theme) {
if (!themeManager.setActiveTheme(settings.merged.ui?.theme)) {
// If the theme is not found during initial load, log a warning and continue.
// The useThemeCommand hook in App.tsx will handle opening the dialog.
// The useThemeCommand hook in AppContainer.tsx will handle opening the dialog.
console.warn(`Warning: Theme "${settings.merged.ui?.theme}" not found.`);
}
}
const initializationResult = await initializeApp(config, settings);
// hop into sandbox if we are outside and sandboxing is enabled
if (!process.env['SANDBOX']) {
const memoryArgs = settings.merged.advanced?.autoConfigureMemory
@@ -403,7 +437,13 @@ export async function main() {
if (config.isInteractive()) {
// Need kitty detection to be complete before we can start the interactive UI.
await kittyProtocolDetectionComplete;
await startInteractiveUI(config, settings, startupWarnings);
await startInteractiveUI(
config,
settings,
startupWarnings,
process.cwd(),
initializationResult,
);
return;
}
// If not a TTY, read from stdin