mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
update to height based on all available height module fix overflow
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useReducer,
|
useReducer,
|
||||||
useContext,
|
useContext,
|
||||||
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { Box, Text } from 'ink';
|
import { Box, Text } from 'ink';
|
||||||
import { theme } from '../semantic-colors.js';
|
import { theme } from '../semantic-colors.js';
|
||||||
@@ -782,28 +783,28 @@ const ChoiceQuestionView: React.FC<ChoiceQuestionViewProps> = ({
|
|||||||
}
|
}
|
||||||
}, [customOptionText, isCustomOptionSelected, question.multiSelect]);
|
}, [customOptionText, isCustomOptionSelected, question.multiSelect]);
|
||||||
|
|
||||||
|
const [actualQuestionHeight, setActualQuestionHeight] = useState(0);
|
||||||
|
|
||||||
const HEADER_HEIGHT = progressHeader ? 2 : 0;
|
const HEADER_HEIGHT = progressHeader ? 2 : 0;
|
||||||
const TITLE_MARGIN = 1;
|
const TITLE_MARGIN = 1;
|
||||||
const FOOTER_HEIGHT = 2; // DialogFooter + margin
|
const FOOTER_HEIGHT = 2; // DialogFooter + margin
|
||||||
const overhead = HEADER_HEIGHT + TITLE_MARGIN + FOOTER_HEIGHT;
|
const overhead = HEADER_HEIGHT + TITLE_MARGIN + FOOTER_HEIGHT;
|
||||||
|
|
||||||
const listHeight = availableHeight
|
const listHeight = availableHeight
|
||||||
? Math.max(1, availableHeight - overhead)
|
? Math.max(1, availableHeight - overhead)
|
||||||
: undefined;
|
: undefined;
|
||||||
const maxQuestionHeight =
|
|
||||||
question.unconstrainedHeight && listHeight
|
// Modulo the fixed overflow (overhead + 4 lines reserved for list), use all remaining height.
|
||||||
? // When unconstrained, give the question a majority of the vertical space (e.g., 70%).
|
const maxQuestionHeight = listHeight ? Math.max(5, listHeight - 4) : 15;
|
||||||
// The options list will take the remaining space and scroll if necessary.
|
|
||||||
// This is more robust than calculating based on `selectionItems.length`,
|
const questionHeightLimit =
|
||||||
// which can incorrectly shrink the question if there are many options.
|
|
||||||
Math.max(5, Math.floor(listHeight * 0.7))
|
|
||||||
: 15;
|
|
||||||
const questionHeight =
|
|
||||||
listHeight && !isAlternateBuffer
|
listHeight && !isAlternateBuffer
|
||||||
? Math.min(maxQuestionHeight, Math.max(1, listHeight - DIALOG_PADDING))
|
? Math.min(maxQuestionHeight, listHeight)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const maxItemsToShow =
|
const maxItemsToShow =
|
||||||
listHeight && questionHeight
|
listHeight && actualQuestionHeight
|
||||||
? Math.max(1, Math.floor((listHeight - questionHeight) / 2))
|
? Math.max(1, Math.floor((listHeight - actualQuestionHeight) / 2))
|
||||||
: selectionItems.length;
|
: selectionItems.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -811,9 +812,10 @@ const ChoiceQuestionView: React.FC<ChoiceQuestionViewProps> = ({
|
|||||||
{progressHeader}
|
{progressHeader}
|
||||||
<Box marginBottom={TITLE_MARGIN}>
|
<Box marginBottom={TITLE_MARGIN}>
|
||||||
<MaxSizedBox
|
<MaxSizedBox
|
||||||
maxHeight={questionHeight}
|
maxHeight={questionHeightLimit}
|
||||||
maxWidth={availableWidth}
|
maxWidth={availableWidth}
|
||||||
overflowDirection="bottom"
|
overflowDirection="bottom"
|
||||||
|
onHeightChange={setActualQuestionHeight}
|
||||||
>
|
>
|
||||||
<Box flexDirection="column">
|
<Box flexDirection="column">
|
||||||
<MarkdownDisplay
|
<MarkdownDisplay
|
||||||
|
|||||||
@@ -282,9 +282,10 @@ describe('ToolConfirmationQueue', () => {
|
|||||||
// hideToolIdentity is true for ask_user -> subtracts 4 instead of 6
|
// hideToolIdentity is true for ask_user -> subtracts 4 instead of 6
|
||||||
// availableContentHeight = 19 - 4 = 15
|
// availableContentHeight = 19 - 4 = 15
|
||||||
// ToolConfirmationMessage handlesOwnUI=true -> returns full 15
|
// ToolConfirmationMessage handlesOwnUI=true -> returns full 15
|
||||||
// AskUserDialog allocates questionHeight = Math.min(maxQuestionHeight, Math.max(5, listHeight - DIALOG_PADDING)).
|
// AskUserDialog allocates questionHeight = availableHeight - overhead - minListHeight.
|
||||||
// maxQuestionHeight = floor(15 * 0.7) = 10.
|
// listHeight = 15 - overhead (Header:0, Margin:1, Footer:2) = 12.
|
||||||
// 10 lines is enough for the 6-line question + padding.
|
// maxQuestionHeight = listHeight - 4 = 8.
|
||||||
|
// 8 lines is enough for the 6-line question.
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(lastFrame()).toContain('Line 6');
|
expect(lastFrame()).toContain('Line 6');
|
||||||
expect(lastFrame()).not.toContain('lines hidden');
|
expect(lastFrame()).not.toContain('lines hidden');
|
||||||
|
|||||||
@@ -36,6 +36,22 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
|
|||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 2`] = `
|
||||||
|
"Choose an option
|
||||||
|
|
||||||
|
▲
|
||||||
|
● 1. Option 1
|
||||||
|
Description 1
|
||||||
|
2. Option 2
|
||||||
|
Description 2
|
||||||
|
3. Option 3
|
||||||
|
Description 3
|
||||||
|
▼
|
||||||
|
|
||||||
|
Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 1`] = `
|
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 1`] = `
|
||||||
"Choose an option
|
"Choose an option
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ interface MaxSizedBoxProps {
|
|||||||
maxHeight?: number;
|
maxHeight?: number;
|
||||||
overflowDirection?: 'top' | 'bottom';
|
overflowDirection?: 'top' | 'bottom';
|
||||||
additionalHiddenLinesCount?: number;
|
additionalHiddenLinesCount?: number;
|
||||||
|
onHeightChange?: (height: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +39,7 @@ export const MaxSizedBox: React.FC<MaxSizedBoxProps> = ({
|
|||||||
maxHeight,
|
maxHeight,
|
||||||
overflowDirection = 'top',
|
overflowDirection = 'top',
|
||||||
additionalHiddenLinesCount = 0,
|
additionalHiddenLinesCount = 0,
|
||||||
|
onHeightChange,
|
||||||
}) => {
|
}) => {
|
||||||
const id = useId();
|
const id = useId();
|
||||||
const { addOverflowingId, removeOverflowingId } = useOverflowActions() || {};
|
const { addOverflowingId, removeOverflowingId } = useOverflowActions() || {};
|
||||||
@@ -80,6 +82,18 @@ export const MaxSizedBox: React.FC<MaxSizedBoxProps> = ({
|
|||||||
? effectiveMaxHeight - 1
|
? effectiveMaxHeight - 1
|
||||||
: effectiveMaxHeight;
|
: effectiveMaxHeight;
|
||||||
|
|
||||||
|
const actualHeight =
|
||||||
|
visibleContentHeight !== undefined
|
||||||
|
? Math.min(contentHeight, visibleContentHeight)
|
||||||
|
: contentHeight;
|
||||||
|
|
||||||
|
const totalActualHeight =
|
||||||
|
actualHeight + (isOverflowing && effectiveMaxHeight !== undefined ? 1 : 0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onHeightChange?.(totalActualHeight);
|
||||||
|
}, [totalActualHeight, onHeightChange]);
|
||||||
|
|
||||||
const hiddenLinesCount =
|
const hiddenLinesCount =
|
||||||
visibleContentHeight !== undefined
|
visibleContentHeight !== undefined
|
||||||
? Math.max(0, contentHeight - visibleContentHeight)
|
? Math.max(0, contentHeight - visibleContentHeight)
|
||||||
|
|||||||
Reference in New Issue
Block a user