/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { Box, useIsScreenReaderEnabled } from 'ink'; import { useCallback, useState } from 'react'; import { LoadingIndicator } from './LoadingIndicator.js'; import { InputPrompt } from './InputPrompt.js'; import { Footer } from './Footer.js'; import { QueuedMessageDisplay } from './QueuedMessageDisplay.js'; import { KeyboardShortcuts } from './KeyboardShortcuts.js'; import { useUIState } from '../contexts/UIStateContext.js'; import { useUIActions } from '../contexts/UIActionsContext.js'; import { useVimMode } from '../contexts/VimModeContext.js'; import { useConfig } from '../contexts/ConfigContext.js'; import { StreamingState } from '../types.js'; import { ConfigInitDisplay } from '../components/ConfigInitDisplay.js'; import { FeedbackDialog } from '../FeedbackDialog.js'; import { t } from '../../i18n/index.js'; export const Composer = () => { const config = useConfig(); const isScreenReaderEnabled = useIsScreenReaderEnabled(); const uiState = useUIState(); const uiActions = useUIActions(); const { vimEnabled } = useVimMode(); const { showAutoAcceptIndicator, sessionStats, taskStartTokens } = uiState; const tokens = Object.values(sessionStats.metrics?.models ?? {}).reduce( (acc, model) => ({ prompt: acc.prompt + (model.tokens?.prompt ?? 0), candidates: acc.candidates + (model.tokens?.candidates ?? 0), }), { prompt: 0, candidates: 0 }, ); const taskTokens = tokens.candidates - taskStartTokens; // State for keyboard shortcuts display toggle const [showShortcuts, setShowShortcuts] = useState(false); const handleToggleShortcuts = useCallback(() => { setShowShortcuts((prev) => !prev); }, []); // State for suggestions visibility const [showSuggestions, setShowSuggestions] = useState(false); const handleSuggestionsVisibilityChange = useCallback( (visible: boolean) => { setShowSuggestions(visible); // Also notify AppContainer for Tab key handling uiActions.onSuggestionsVisibilityChange(visible); }, [uiActions], ); return ( {!uiState.embeddedShellFocused && ( )} {!uiState.isConfigInitialized && } {uiState.isFeedbackDialogOpen && } {uiState.isInputActive && ( )} {/* Exclusive area: only one component visible at a time */} {/* Hide footer when a confirmation dialog (e.g. ask_user_question) is active */} {uiState.isInputActive && !showSuggestions && (showShortcuts ? ( ) : ( !isScreenReaderEnabled &&