/** * @license * Copyright 2026 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { Box, useIsScreenReaderEnabled } from 'ink'; import { useState, useEffect } from 'react'; import { useConfig } from '../contexts/ConfigContext.js'; import { useSettings } from '../contexts/SettingsContext.js'; import { useUIState } from '../contexts/UIStateContext.js'; import { useUIActions } from '../contexts/UIActionsContext.js'; import { useVimMode } from '../contexts/VimModeContext.js'; import { useAlternateBuffer } from '../hooks/useAlternateBuffer.js'; import { useTerminalSize } from '../hooks/useTerminalSize.js'; import { isNarrowWidth } from '../utils/isNarrowWidth.js'; import { ToastDisplay, shouldShowToast } from './ToastDisplay.js'; import { DetailedMessagesDisplay } from './DetailedMessagesDisplay.js'; import { ShortcutsHelp } from './ShortcutsHelp.js'; import { InputPrompt } from './InputPrompt.js'; import { Footer } from './Footer.js'; import { StatusRow } from './StatusRow.js'; import { ShowMoreLines } from './ShowMoreLines.js'; import { QueuedMessageDisplay } from './QueuedMessageDisplay.js'; import { OverflowProvider } from '../contexts/OverflowContext.js'; import { ConfigInitDisplay } from './ConfigInitDisplay.js'; import { TodoTray } from './messages/Todo.js'; import { useComposerStatus } from '../hooks/useComposerStatus.js'; export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { const uiState = useUIState(); const uiActions = useUIActions(); const settings = useSettings(); const config = useConfig(); const { vimEnabled, vimMode } = useVimMode(); const isScreenReaderEnabled = useIsScreenReaderEnabled(); const { columns: terminalWidth } = useTerminalSize(); const isNarrow = isNarrowWidth(terminalWidth); const debugConsoleMaxHeight = Math.floor(Math.max(terminalWidth * 0.2, 5)); const [suggestionsVisible, setSuggestionsVisible] = useState(false); const isAlternateBuffer = useAlternateBuffer(); const showUiDetails = uiState.cleanUiDetailsVisible; const suggestionsPosition = isAlternateBuffer ? 'above' : 'below'; const hideContextSummary = suggestionsVisible && suggestionsPosition === 'above'; const { hasPendingActionRequired, shouldCollapseDuringApproval } = useComposerStatus(); const isPassiveShortcutsHelpState = uiState.isInputActive && uiState.streamingState === 'idle' && !hasPendingActionRequired; const { setShortcutsHelpVisible } = uiActions; useEffect(() => { if (uiState.shortcutsHelpVisible && !isPassiveShortcutsHelpState) { setShortcutsHelpVisible(false); } }, [ uiState.shortcutsHelpVisible, isPassiveShortcutsHelpState, setShortcutsHelpVisible, ]); const showShortcutsHelp = uiState.shortcutsHelpVisible && uiState.streamingState === 'idle' && !hasPendingActionRequired; if (hasPendingActionRequired && shouldCollapseDuringApproval) { return null; } const hasToast = shouldShowToast(uiState); const hideUiDetailsForSuggestions = suggestionsVisible && suggestionsPosition === 'above'; // Mini Mode VIP Flags (Pure Content Triggers) const showMinimalToast = hasToast; return ( {uiState.isResuming && ( )} {showUiDetails && ( )} {showUiDetails && } {showShortcutsHelp && } {(showUiDetails || showMinimalToast) && ( )} {showUiDetails && uiState.showErrorDetails && ( )} {uiState.isInputActive && ( )} {showUiDetails && !settings.merged.ui.hideFooter && !isScreenReaderEnabled && (