From 9c46acc793df3573e6fbcf53ac3e46663494e410 Mon Sep 17 00:00:00 2001
From: Taylor Mullen <ntaylormullen@google.com>
Date: Thu, 15 May 2025 22:56:03 -0700
Subject: Refactor: Improve UI rendering and address code review comments

This commit addresses several code review comments primarily focused on improving the rendering and stability of the CLI UI.

Key changes include:
- Passing `isPending` and `availableTerminalHeight` props to `MarkdownDisplay` to enable more intelligent rendering of content, especially for pending messages and code blocks.
- Adjusting height calculations in `ToolGroupMessage` and `ToolMessage` to more accurately reflect available space.
- Refining the logic in `App.tsx` for measuring and utilizing terminal height, including renaming `footerRef` to `mainControlsRef` for clarity.
- Ensuring consistent prop drilling for `isPending` and `availableTerminalHeight` through `HistoryItemDisplay`, `GeminiMessage`, and `GeminiMessageContent`.
- In `MarkdownDisplay`, when `isPending` is true and content exceeds `availableTerminalHeight`, the code block will now be truncated with a "... generating more ..." message. If there's insufficient space even for the
message, a simpler "... code is being written ..." will be shown.
---
 packages/cli/src/ui/utils/MarkdownDisplay.tsx | 49 ++++++++++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)

(limited to 'packages/cli/src/ui/utils/MarkdownDisplay.tsx')

diff --git a/packages/cli/src/ui/utils/MarkdownDisplay.tsx b/packages/cli/src/ui/utils/MarkdownDisplay.tsx
index 63888a8b..83fb46ee 100644
--- a/packages/cli/src/ui/utils/MarkdownDisplay.tsx
+++ b/packages/cli/src/ui/utils/MarkdownDisplay.tsx
@@ -11,6 +11,8 @@ import { colorizeCode } from './CodeColorizer.js';
 
 interface MarkdownDisplayProps {
   text: string;
+  isPending: boolean;
+  availableTerminalHeight: number;
 }
 
 // Constants for Markdown parsing and rendering
@@ -26,7 +28,11 @@ const CODE_BLOCK_PADDING = 1;
 const LIST_ITEM_PREFIX_PADDING = 1;
 const LIST_ITEM_TEXT_FLEX_GROW = 1;
 
-const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ text }) => {
+const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({
+  text,
+  isPending,
+  availableTerminalHeight,
+}) => {
   if (!text) return <></>;
 
   const lines = text.split('\n');
@@ -57,6 +63,8 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ text }) => {
             key={key}
             content={codeBlockContent}
             lang={codeBlockLang}
+            isPending={isPending}
+            availableTerminalHeight={availableTerminalHeight}
           />,
         );
         inCodeBlock = false;
@@ -176,6 +184,8 @@ const MarkdownDisplayInternal: React.FC<MarkdownDisplayProps> = ({ text }) => {
         key="line-eof"
         content={codeBlockContent}
         lang={codeBlockLang}
+        isPending={isPending}
+        availableTerminalHeight={availableTerminalHeight}
       />,
     );
   }
@@ -317,12 +327,49 @@ const RenderInline = React.memo(RenderInlineInternal);
 interface RenderCodeBlockProps {
   content: string[];
   lang: string | null;
+  isPending: boolean;
+  availableTerminalHeight: number;
 }
 
 const RenderCodeBlockInternal: React.FC<RenderCodeBlockProps> = ({
   content,
   lang,
+  isPending,
+  availableTerminalHeight,
 }) => {
+  const MIN_LINES_FOR_MESSAGE = 1; // Minimum lines to show before the "generating more" message
+  const RESERVED_LINES = 2; // Lines reserved for the message itself and potential padding
+  const MAX_CODE_LINES_WHEN_PENDING = Math.max(
+    0,
+    availableTerminalHeight - CODE_BLOCK_PADDING * 2 - RESERVED_LINES,
+  );
+
+  if (isPending) {
+    if (content.length > MAX_CODE_LINES_WHEN_PENDING) {
+      if (MAX_CODE_LINES_WHEN_PENDING < MIN_LINES_FOR_MESSAGE) {
+        // Not enough space to even show the message meaningfully
+        return (
+          <Box padding={CODE_BLOCK_PADDING}>
+            <Text color={Colors.SubtleComment}>
+              ... code is being written ...
+            </Text>
+          </Box>
+        );
+      }
+      const truncatedContent = content.slice(0, MAX_CODE_LINES_WHEN_PENDING);
+      const colorizedTruncatedCode = colorizeCode(
+        truncatedContent.join('\n'),
+        lang,
+      );
+      return (
+        <Box flexDirection="column" padding={CODE_BLOCK_PADDING}>
+          {colorizedTruncatedCode}
+          <Text color={Colors.SubtleComment}>... generating more ...</Text>
+        </Box>
+      );
+    }
+  }
+
   const fullContent = content.join('\n');
   const colorizedCode = colorizeCode(fullContent, lang);
 
-- 
cgit v1.2.3

