mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-19 02:20:42 -07:00
chore: reduce duplication
This commit is contained in:
committed by
Keith Guerin
parent
c51925b58a
commit
4412314dbe
@@ -61,12 +61,6 @@ export const ALL_ITEMS = [
|
||||
|
||||
export type FooterItemId = (typeof ALL_ITEMS)[number]['id'];
|
||||
|
||||
export interface FooterItem {
|
||||
id: string;
|
||||
header: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_ORDER = [
|
||||
'cwd',
|
||||
'git-branch',
|
||||
|
||||
@@ -101,6 +101,52 @@ const CorgiIndicator: React.FC = () => (
|
||||
</Text>
|
||||
);
|
||||
|
||||
export interface FooterRowItem {
|
||||
key: string;
|
||||
header: string;
|
||||
element: React.ReactNode;
|
||||
}
|
||||
|
||||
const COLUMN_GAP = 3;
|
||||
|
||||
export const FooterRow: React.FC<{
|
||||
items: FooterRowItem[];
|
||||
showLabels: boolean;
|
||||
}> = ({ items, showLabels }) => {
|
||||
const elements: React.ReactNode[] = [];
|
||||
|
||||
items.forEach((item, idx) => {
|
||||
if (idx > 0 && !showLabels) {
|
||||
elements.push(
|
||||
<Box key={`sep-${item.key}`} height={1}>
|
||||
<Text color={theme.ui.comment}> · </Text>
|
||||
</Box>,
|
||||
);
|
||||
}
|
||||
|
||||
elements.push(
|
||||
<Box key={item.key} flexDirection="column">
|
||||
{showLabels && (
|
||||
<Box height={1}>
|
||||
<Text color={theme.ui.comment}>{item.header}</Text>
|
||||
</Box>
|
||||
)}
|
||||
<Box height={1}>{item.element}</Box>
|
||||
</Box>,
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Box
|
||||
flexDirection="row"
|
||||
flexWrap="nowrap"
|
||||
columnGap={showLabels ? COLUMN_GAP : 0}
|
||||
>
|
||||
{elements}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
function isFooterItemId(id: string): id is FooterItemId {
|
||||
return ALL_ITEMS.some((i) => i.id === id);
|
||||
}
|
||||
@@ -251,21 +297,19 @@ export const Footer: React.FC = () => {
|
||||
break;
|
||||
}
|
||||
case 'context-remaining': {
|
||||
if (!settings.merged.ui.footer.hideContextPercentage) {
|
||||
addCol(
|
||||
id,
|
||||
header,
|
||||
() => (
|
||||
<ContextUsageDisplay
|
||||
promptTokenCount={promptTokenCount}
|
||||
model={model}
|
||||
terminalWidth={terminalWidth}
|
||||
color={itemColor}
|
||||
/>
|
||||
),
|
||||
10, // "100% left" is 9 chars
|
||||
);
|
||||
}
|
||||
addCol(
|
||||
id,
|
||||
header,
|
||||
() => (
|
||||
<ContextUsageDisplay
|
||||
promptTokenCount={promptTokenCount}
|
||||
model={model}
|
||||
terminalWidth={terminalWidth}
|
||||
color={itemColor}
|
||||
/>
|
||||
),
|
||||
10, // "100% left" is 9 chars
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'quota': {
|
||||
@@ -366,7 +410,6 @@ export const Footer: React.FC = () => {
|
||||
}
|
||||
|
||||
// --- Width Fitting Logic ---
|
||||
const COLUMN_GAP = 3;
|
||||
let currentWidth = 2; // Initial padding
|
||||
const columnsToRender: FooterColumn[] = [];
|
||||
let droppedAny = false;
|
||||
@@ -396,58 +439,26 @@ export const Footer: React.FC = () => {
|
||||
);
|
||||
const excessSpace = Math.max(0, terminalWidth - totalBudgeted);
|
||||
|
||||
const finalElements: React.ReactNode[] = [];
|
||||
|
||||
columnsToRender.forEach((col, idx) => {
|
||||
if (idx > 0 && !showLabels) {
|
||||
finalElements.push(
|
||||
<Box key={`sep-${col.id}`} height={1}>
|
||||
<Text color={theme.ui.comment}> · </Text>
|
||||
</Box>,
|
||||
);
|
||||
}
|
||||
|
||||
const rowItems: FooterRowItem[] = columnsToRender.map((col) => {
|
||||
const maxWidth = col.id === 'cwd' ? 20 + excessSpace : col.width;
|
||||
finalElements.push(
|
||||
<Box key={col.id} flexDirection="column">
|
||||
{showLabels && (
|
||||
<Box height={1}>
|
||||
<Text color={theme.ui.comment}>{col.header}</Text>
|
||||
</Box>
|
||||
)}
|
||||
<Box height={1}>{col.element(maxWidth)}</Box>
|
||||
</Box>,
|
||||
);
|
||||
return {
|
||||
key: col.id,
|
||||
header: col.header,
|
||||
element: col.element(maxWidth),
|
||||
};
|
||||
});
|
||||
|
||||
if (droppedAny) {
|
||||
if (!showLabels) {
|
||||
finalElements.push(
|
||||
<Box key="sep-ellipsis" height={1}>
|
||||
<Text color={theme.ui.comment}> · </Text>
|
||||
</Box>,
|
||||
);
|
||||
}
|
||||
finalElements.push(
|
||||
<Box key="ellipsis" flexDirection="column">
|
||||
{showLabels && <Box height={1} />}
|
||||
<Box height={1}>
|
||||
<Text color={theme.ui.comment}>…</Text>
|
||||
</Box>
|
||||
</Box>,
|
||||
);
|
||||
rowItems.push({
|
||||
key: 'ellipsis',
|
||||
header: '',
|
||||
element: <Text color={theme.ui.comment}>…</Text>,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
width={terminalWidth}
|
||||
flexDirection="row"
|
||||
paddingX={1}
|
||||
overflow="hidden"
|
||||
flexWrap="nowrap"
|
||||
columnGap={showLabels ? COLUMN_GAP : 0}
|
||||
>
|
||||
{finalElements}
|
||||
<Box width={terminalWidth} paddingX={1} overflow="hidden" flexWrap="nowrap">
|
||||
<FooterRow items={rowItems} showLabels={showLabels} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ import { keyMatchers, Command } from '../keyMatchers.js';
|
||||
import { TextInput } from './shared/TextInput.js';
|
||||
import { useFuzzyList } from '../hooks/useFuzzyList.js';
|
||||
import { MemoryUsageDisplay } from './MemoryUsageDisplay.js';
|
||||
import { FooterRow, type FooterRowItem } from './Footer.js';
|
||||
import {
|
||||
ALL_ITEMS,
|
||||
DEFAULT_ORDER,
|
||||
@@ -316,98 +317,47 @@ export const FooterConfigDialog: React.FC<FooterConfigDialogProps> = ({
|
||||
const getColor = (id: string, defaultColor?: string) =>
|
||||
id === activeId ? 'white' : defaultColor || itemColor;
|
||||
|
||||
// Mock values for preview
|
||||
const mockValues: Record<
|
||||
string,
|
||||
{ header: string; data: React.ReactNode }
|
||||
> = {
|
||||
cwd: {
|
||||
header: 'Path',
|
||||
data: <Text color={getColor('cwd', itemColor)}>~/project/path</Text>,
|
||||
},
|
||||
'git-branch': {
|
||||
header: 'Branch',
|
||||
data: <Text color={getColor('git-branch', itemColor)}>main</Text>,
|
||||
},
|
||||
'sandbox-status': {
|
||||
header: '/docs',
|
||||
data: <Text color={getColor('sandbox-status', 'green')}>docker</Text>,
|
||||
},
|
||||
'model-name': {
|
||||
header: '/model',
|
||||
data: (
|
||||
<Text color={getColor('model-name', itemColor)}>gemini-2.5-pro</Text>
|
||||
),
|
||||
},
|
||||
'context-remaining': {
|
||||
header: 'Context',
|
||||
data: (
|
||||
<Text color={getColor('context-remaining', itemColor)}>85% left</Text>
|
||||
),
|
||||
},
|
||||
quota: {
|
||||
header: '/stats',
|
||||
data: <Text color={getColor('quota', itemColor)}>daily 97%</Text>,
|
||||
},
|
||||
'memory-usage': {
|
||||
header: 'Memory',
|
||||
data: <MemoryUsageDisplay color={itemColor} />,
|
||||
},
|
||||
'session-id': {
|
||||
header: 'Session',
|
||||
data: <Text color={getColor('session-id', itemColor)}>769992f9</Text>,
|
||||
},
|
||||
'code-changes': {
|
||||
header: 'Diff',
|
||||
data: (
|
||||
<Box flexDirection="row">
|
||||
<Text color={getColor('code-changes', theme.status.success)}>
|
||||
+12
|
||||
</Text>
|
||||
<Text color={getColor('code-changes')}> </Text>
|
||||
<Text color={getColor('code-changes', theme.status.error)}>-4</Text>
|
||||
</Box>
|
||||
),
|
||||
},
|
||||
'token-count': {
|
||||
header: 'Tokens',
|
||||
data: (
|
||||
<Text color={getColor('token-count', itemColor)}>1.5k tokens</Text>
|
||||
),
|
||||
},
|
||||
// Mock data for preview (headers come from ALL_ITEMS)
|
||||
const mockData: Record<string, React.ReactNode> = {
|
||||
cwd: <Text color={getColor('cwd', itemColor)}>~/project/path</Text>,
|
||||
'git-branch': <Text color={getColor('git-branch', itemColor)}>main</Text>,
|
||||
'sandbox-status': (
|
||||
<Text color={getColor('sandbox-status', 'green')}>docker</Text>
|
||||
),
|
||||
'model-name': (
|
||||
<Text color={getColor('model-name', itemColor)}>gemini-2.5-pro</Text>
|
||||
),
|
||||
'context-remaining': (
|
||||
<Text color={getColor('context-remaining', itemColor)}>85% left</Text>
|
||||
),
|
||||
quota: <Text color={getColor('quota', itemColor)}>daily 97%</Text>,
|
||||
'memory-usage': <MemoryUsageDisplay color={itemColor} />,
|
||||
'session-id': (
|
||||
<Text color={getColor('session-id', itemColor)}>769992f9</Text>
|
||||
),
|
||||
'code-changes': (
|
||||
<Box flexDirection="row">
|
||||
<Text color={getColor('code-changes', theme.status.success)}>
|
||||
+12
|
||||
</Text>
|
||||
<Text color={getColor('code-changes')}> </Text>
|
||||
<Text color={getColor('code-changes', theme.status.error)}>-4</Text>
|
||||
</Box>
|
||||
),
|
||||
'token-count': (
|
||||
<Text color={getColor('token-count', itemColor)}>1.5k tokens</Text>
|
||||
),
|
||||
};
|
||||
|
||||
const previewElements: React.ReactNode[] = [];
|
||||
const rowItems: FooterRowItem[] = itemsToPreview
|
||||
.filter((id: string) => mockData[id])
|
||||
.map((id: string) => ({
|
||||
key: id,
|
||||
header: ALL_ITEMS.find((i) => i.id === id)?.header ?? id,
|
||||
element: mockData[id],
|
||||
}));
|
||||
|
||||
itemsToPreview.forEach((id: string, idx: number) => {
|
||||
const mock = mockValues[id];
|
||||
if (!mock) return;
|
||||
|
||||
if (idx > 0 && !showLabels) {
|
||||
previewElements.push(
|
||||
<Box key={`sep-${id}`} height={1}>
|
||||
<Text color={theme.ui.comment}> · </Text>
|
||||
</Box>,
|
||||
);
|
||||
}
|
||||
|
||||
previewElements.push(
|
||||
<Box key={id} flexDirection="column">
|
||||
{showLabels && (
|
||||
<Box height={1}>
|
||||
<Text color={theme.ui.comment}>{mock.header}</Text>
|
||||
</Box>
|
||||
)}
|
||||
<Box height={1}>{mock.data}</Box>
|
||||
</Box>,
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Box flexDirection="row" flexWrap="nowrap" columnGap={showLabels ? 3 : 0}>
|
||||
{previewElements}
|
||||
</Box>
|
||||
);
|
||||
return <FooterRow items={rowItems} showLabels={showLabels} />;
|
||||
}, [orderedIds, selectedIds, activeId, isResetFocused, showLabels]);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user