Fix TUI redraw artifacts in row-based views (#325)
Co-authored-by: pr0ln <pr0ln@pr0lnui-Macmini.local>
This commit is contained in:
@@ -9,6 +9,7 @@ import { formatDuration, formatNumber } from '../../utils/format.js';
|
||||
import { toInkColor } from '../../utils/ink.js';
|
||||
import type { Theme } from '../../utils/theme.js';
|
||||
import { Byline } from '../design-system/Byline.js';
|
||||
import FullWidthRow from '../design-system/FullWidthRow.js';
|
||||
import { GlimmerMessage } from './GlimmerMessage.js';
|
||||
import { SpinnerGlyph } from './SpinnerGlyph.js';
|
||||
import type { SpinnerMode } from './types.js';
|
||||
@@ -223,11 +224,13 @@ export function SpinnerAnimationRow({
|
||||
<Byline>{parts}</Byline>
|
||||
<Text dimColor>)</Text>
|
||||
</> : null;
|
||||
return <Box ref={viewportRef} flexDirection="row" flexWrap="wrap" marginTop={1} width="100%">
|
||||
return <FullWidthRow>
|
||||
<Box ref={viewportRef} flexDirection="row" flexWrap="wrap" marginTop={1}>
|
||||
<SpinnerGlyph frame={frame} messageColor={messageColor} stalledIntensity={overrideColor ? 0 : stalledIntensity} reducedMotion={reducedMotion} time={time} />
|
||||
<GlimmerMessage message={message} mode={mode} messageColor={messageColor} glimmerIndex={glimmerIndex} flashOpacity={flashOpacity} shimmerColor={shimmerColor} stalledIntensity={overrideColor ? 0 : stalledIntensity} />
|
||||
{status}
|
||||
</Box>;
|
||||
</Box>
|
||||
</FullWidthRow>;
|
||||
}
|
||||
function SpinnerModeGlyph(t0) {
|
||||
const $ = _c(2);
|
||||
|
||||
@@ -13,6 +13,7 @@ import { summarizeRecentActivities } from '../utils/collapseReadSearch.js';
|
||||
import { truncateToWidth } from '../utils/format.js';
|
||||
import { isTodoV2Enabled, type Task } from '../utils/tasks.js';
|
||||
import type { Theme } from '../utils/theme.js';
|
||||
import FullWidthRow from './design-system/FullWidthRow.js';
|
||||
import ThemedText from './design-system/ThemedText.js';
|
||||
type Props = {
|
||||
tasks: Task[];
|
||||
@@ -186,11 +187,11 @@ export function TaskListV2({
|
||||
}
|
||||
const content = <>
|
||||
{visibleTasks.map(task_0 => <TaskItem key={task_0.id} task={task_0} ownerColor={task_0.owner ? teammateColors[task_0.owner] : undefined} openBlockers={task_0.blockedBy.filter(id_3 => unresolvedTaskIds.has(id_3))} activity={task_0.owner ? teammateActivity[task_0.owner] : undefined} ownerActive={task_0.owner ? activeTeammates.has(task_0.owner) : false} columns={columns} />)}
|
||||
{maxDisplay > 0 && hiddenSummary && <Text dimColor>{hiddenSummary}</Text>}
|
||||
{maxDisplay > 0 && hiddenSummary && <FullWidthRow><Text dimColor>{hiddenSummary}</Text></FullWidthRow>}
|
||||
</>;
|
||||
if (isStandalone) {
|
||||
return <Box flexDirection="column" marginTop={1} marginLeft={2}>
|
||||
<Box>
|
||||
return <Box flexDirection="column" marginTop={1} marginLeft={2} width="100%">
|
||||
<Box width="100%">
|
||||
<Text dimColor>
|
||||
<Text bold>{tasks.length}</Text>
|
||||
{' tasks ('}
|
||||
@@ -207,7 +208,7 @@ export function TaskListV2({
|
||||
{content}
|
||||
</Box>;
|
||||
}
|
||||
return <Box flexDirection="column">{content}</Box>;
|
||||
return <Box flexDirection="column" width="100%">{content}</Box>;
|
||||
}
|
||||
type TaskItemProps = {
|
||||
task: Task;
|
||||
@@ -340,7 +341,7 @@ function TaskItem(t0) {
|
||||
}
|
||||
let t10;
|
||||
if ($[26] !== t5 || $[27] !== t7 || $[28] !== t8 || $[29] !== t9) {
|
||||
t10 = <Box>{t5}{t7}{t8}{t9}</Box>;
|
||||
t10 = <FullWidthRow>{t5}{t7}{t8}{t9}</FullWidthRow>;
|
||||
$[26] = t5;
|
||||
$[27] = t7;
|
||||
$[28] = t8;
|
||||
@@ -351,7 +352,7 @@ function TaskItem(t0) {
|
||||
}
|
||||
let t11;
|
||||
if ($[31] !== displayActivity || $[32] !== showActivity) {
|
||||
t11 = showActivity && displayActivity && <Box><Text dimColor={true}>{" "}{displayActivity}{figures.ellipsis}</Text></Box>;
|
||||
t11 = showActivity && displayActivity && <FullWidthRow><Text dimColor={true}>{" "}{displayActivity}{figures.ellipsis}</Text></FullWidthRow>;
|
||||
$[31] = displayActivity;
|
||||
$[32] = showActivity;
|
||||
$[33] = t11;
|
||||
@@ -360,7 +361,7 @@ function TaskItem(t0) {
|
||||
}
|
||||
let t12;
|
||||
if ($[34] !== t10 || $[35] !== t11) {
|
||||
t12 = <Box flexDirection="column">{t10}{t11}</Box>;
|
||||
t12 = <Box flexDirection="column" width="100%">{t10}{t11}</Box>;
|
||||
$[34] = t10;
|
||||
$[35] = t11;
|
||||
$[36] = t12;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useKeybinding } from '../../keybindings/useKeybinding.js';
|
||||
import type { Theme } from '../../utils/theme.js';
|
||||
import { ConfigurableShortcutHint } from '../ConfigurableShortcutHint.js';
|
||||
import { Byline } from './Byline.js';
|
||||
import FullWidthRow from './FullWidthRow.js';
|
||||
import { KeyboardShortcutHint } from './KeyboardShortcutHint.js';
|
||||
import { Pane } from './Pane.js';
|
||||
type DialogProps = {
|
||||
@@ -102,7 +103,7 @@ export function Dialog(t0) {
|
||||
}
|
||||
let t9;
|
||||
if ($[16] !== defaultInputGuide || $[17] !== exitState || $[18] !== hideInputGuide || $[19] !== inputGuide) {
|
||||
t9 = !hideInputGuide && <Box marginTop={1}><Text dimColor={true} italic={true}>{inputGuide ? inputGuide(exitState) : defaultInputGuide}</Text></Box>;
|
||||
t9 = !hideInputGuide && <Box marginTop={1}><FullWidthRow><Text dimColor={true} italic={true}>{inputGuide ? inputGuide(exitState) : defaultInputGuide}</Text></FullWidthRow></Box>;
|
||||
$[16] = defaultInputGuide;
|
||||
$[17] = exitState;
|
||||
$[18] = hideInputGuide;
|
||||
|
||||
15
src/components/design-system/FullWidthRow.tsx
Normal file
15
src/components/design-system/FullWidthRow.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import { Box } from '../../ink.js';
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function FullWidthRow({
|
||||
children
|
||||
}: Props): React.ReactNode {
|
||||
return <Box flexDirection="row" width="100%">
|
||||
{children}
|
||||
<Box flexGrow={1} />
|
||||
</Box>;
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import { BLACK_CIRCLE } from '../../constants/figures.js';
|
||||
import { TeammateMessageContent } from './UserTeammateMessage.js';
|
||||
import { isShutdownApproved } from '../../utils/teammateMailbox.js';
|
||||
import { CtrlOToExpand } from '../CtrlOToExpand.js';
|
||||
import FullWidthRow from '../design-system/FullWidthRow.js';
|
||||
import { FilePathLink } from '../FilePathLink.js';
|
||||
import { feature } from 'bun:bundle';
|
||||
import { useSelectedMessageBg } from '../messageActions.js';
|
||||
@@ -514,7 +515,7 @@ function Line(t0) {
|
||||
const bg = useSelectedMessageBg();
|
||||
let t2;
|
||||
if ($[0] !== children || $[1] !== color || $[2] !== dimColor) {
|
||||
t2 = <MessageResponse><Text color={color} dimColor={dimColor} wrap="wrap">{children}</Text></MessageResponse>;
|
||||
t2 = <MessageResponse><FullWidthRow><Text color={color} dimColor={dimColor} wrap="wrap">{children}</Text></FullWidthRow></MessageResponse>;
|
||||
$[0] = children;
|
||||
$[1] = color;
|
||||
$[2] = dimColor;
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NO_CONTENT_MESSAGE } from '../../constants/messages.js';
|
||||
import { Box, Text } from '../../ink.js';
|
||||
import { extractTag } from '../../utils/messages.js';
|
||||
import { Markdown } from '../Markdown.js';
|
||||
import FullWidthRow from '../design-system/FullWidthRow.js';
|
||||
import { MessageResponse } from '../MessageResponse.js';
|
||||
type Props = {
|
||||
content: string;
|
||||
@@ -77,7 +78,7 @@ function IndentedContent(t0) {
|
||||
}
|
||||
let t2;
|
||||
if ($[3] !== children) {
|
||||
t2 = <Box flexDirection="row">{t1}<Box flexDirection="column" flexGrow={1}><Markdown>{children}</Markdown></Box></Box>;
|
||||
t2 = <FullWidthRow>{t1}<Box flexDirection="column" flexGrow={1}><Markdown>{children}</Markdown></Box></FullWidthRow>;
|
||||
$[3] = children;
|
||||
$[4] = t2;
|
||||
} else {
|
||||
@@ -147,7 +148,7 @@ function CloudLaunchContent(t0) {
|
||||
}
|
||||
let t6;
|
||||
if ($[14] !== rest) {
|
||||
t6 = rest && <Box flexDirection="row"><Text dimColor={true}>{" \u23BF "}</Text><Text dimColor={true}>{rest}</Text></Box>;
|
||||
t6 = rest && <FullWidthRow><Text dimColor={true}>{" \u23BF "}</Text><Text dimColor={true}>{rest}</Text></FullWidthRow>;
|
||||
$[14] = rest;
|
||||
$[15] = t6;
|
||||
} else {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { getSettingSourceName, type SettingSource } from '../../utils/settings/c
|
||||
import { plural } from '../../utils/stringUtils.js';
|
||||
import { ConfigurableShortcutHint } from '../ConfigurableShortcutHint.js';
|
||||
import { Dialog } from '../design-system/Dialog.js';
|
||||
import FullWidthRow from '../design-system/FullWidthRow.js';
|
||||
|
||||
// Skills are always PromptCommands with CommandBase properties
|
||||
type SkillCommand = CommandBase & PromptCommand;
|
||||
@@ -105,14 +106,14 @@ export function SkillsMenu(t0) {
|
||||
if (skills.length === 0) {
|
||||
let t3;
|
||||
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t3 = <Text dimColor={true}>Create skills in .claude/skills/ or ~/.claude/skills/</Text>;
|
||||
t3 = <FullWidthRow><Text dimColor={true}>Create skills in .claude/skills/ or ~/.claude/skills/</Text></FullWidthRow>;
|
||||
$[6] = t3;
|
||||
} else {
|
||||
t3 = $[6];
|
||||
}
|
||||
let t4;
|
||||
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t4 = <Text dimColor={true} italic={true}><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="close" /></Text>;
|
||||
t4 = <FullWidthRow><Text dimColor={true} italic={true}><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="close" /></Text></FullWidthRow>;
|
||||
$[7] = t4;
|
||||
} else {
|
||||
t4 = $[7];
|
||||
@@ -137,7 +138,7 @@ export function SkillsMenu(t0) {
|
||||
}
|
||||
const title = getSourceTitle(source_0);
|
||||
const subtitle = getSourceSubtitle(source_0, groupSkills);
|
||||
return <Box flexDirection="column" key={source_0}><Box><Text bold={true} dimColor={true}>{title}</Text>{subtitle && <Text dimColor={true}> ({subtitle})</Text>}</Box>{groupSkills.map(skill_1 => renderSkill(skill_1))}</Box>;
|
||||
return <Box flexDirection="column" key={source_0}><FullWidthRow><Text bold={true} dimColor={true}>{title}</Text>{subtitle && <Text dimColor={true}> ({subtitle})</Text>}</FullWidthRow>{groupSkills.map(skill_1 => renderSkill(skill_1))}</Box>;
|
||||
};
|
||||
$[10] = skillsBySource;
|
||||
$[11] = t3;
|
||||
@@ -209,7 +210,7 @@ export function SkillsMenu(t0) {
|
||||
}
|
||||
let t13;
|
||||
if ($[30] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t13 = <Text dimColor={true} italic={true}><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="close" /></Text>;
|
||||
t13 = <FullWidthRow><Text dimColor={true} italic={true}><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="close" /></Text></FullWidthRow>;
|
||||
$[30] = t13;
|
||||
} else {
|
||||
t13 = $[30];
|
||||
@@ -230,7 +231,7 @@ function _temp3(skill_0) {
|
||||
const estimatedTokens = estimateSkillFrontmatterTokens(skill_0);
|
||||
const tokenDisplay = `~${formatTokens(estimatedTokens)}`;
|
||||
const pluginName = skill_0.source === "plugin" ? skill_0.pluginInfo?.pluginManifest.name : undefined;
|
||||
return <Box key={`${skill_0.name}-${skill_0.source}`}><Text>{getSkillListLabel(skill_0)}</Text><Text dimColor={true}>{pluginName ? ` · ${pluginName}` : ""} · {tokenDisplay} description tokens</Text></Box>;
|
||||
return <FullWidthRow key={`${skill_0.name}-${skill_0.source}`}><Text>{getSkillListLabel(skill_0)}</Text><Text dimColor={true}>{pluginName ? ` · ${pluginName}` : ""} · {tokenDisplay} description tokens</Text></FullWidthRow>;
|
||||
}
|
||||
function _temp2(a, b) {
|
||||
return a.name.localeCompare(b.name);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { c as _c } from "react-compiler-runtime";
|
||||
import React from 'react';
|
||||
import { removeSandboxViolationTags } from 'src/utils/sandbox/sandbox-ui-utils.js';
|
||||
import FullWidthRow from '../../components/design-system/FullWidthRow.js';
|
||||
import { KeyboardShortcutHint } from '../../components/design-system/KeyboardShortcutHint.js';
|
||||
import { MessageResponse } from '../../components/MessageResponse.js';
|
||||
import { OutputLine } from '../../components/shell/OutputLine.js';
|
||||
@@ -100,7 +101,7 @@ export default function BashToolResultMessage(t0) {
|
||||
if (isImage) {
|
||||
let t8;
|
||||
if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t8 = <MessageResponse height={1}><Text dimColor={true}>[Image data detected and sent to Claude]</Text></MessageResponse>;
|
||||
t8 = <MessageResponse height={1}><FullWidthRow><Text dimColor={true}>[Image data detected and sent to Claude]</Text></FullWidthRow></MessageResponse>;
|
||||
$[11] = t8;
|
||||
} else {
|
||||
t8 = $[11];
|
||||
@@ -145,7 +146,7 @@ export default function BashToolResultMessage(t0) {
|
||||
}
|
||||
let t8;
|
||||
if ($[15] !== cwdResetWarning) {
|
||||
t8 = cwdResetWarning ? <MessageResponse><Text dimColor={true}>{cwdResetWarning}</Text></MessageResponse> : null;
|
||||
t8 = cwdResetWarning ? <MessageResponse><FullWidthRow><Text dimColor={true}>{cwdResetWarning}</Text></FullWidthRow></MessageResponse> : null;
|
||||
$[15] = cwdResetWarning;
|
||||
$[16] = t8;
|
||||
} else {
|
||||
@@ -153,7 +154,7 @@ export default function BashToolResultMessage(t0) {
|
||||
}
|
||||
let t9;
|
||||
if ($[17] !== backgroundTaskId || $[18] !== cwdResetWarning || $[19] !== noOutputExpected || $[20] !== returnCodeInterpretation || $[21] !== stderr || $[22] !== stdout) {
|
||||
t9 = stdout === "" && stderr.trim() === "" && !cwdResetWarning ? <MessageResponse height={1}><Text dimColor={true}>{backgroundTaskId ? <>Running in the background{" "}<KeyboardShortcutHint shortcut={"\u2193"} action="manage" parens={true} /></> : returnCodeInterpretation || (noOutputExpected ? "Done" : "(No output)")}</Text></MessageResponse> : null;
|
||||
t9 = stdout === "" && stderr.trim() === "" && !cwdResetWarning ? <MessageResponse height={1}><FullWidthRow><Text dimColor={true}>{backgroundTaskId ? <>Running in the background{" "}<KeyboardShortcutHint shortcut={"\u2193"} action="manage" parens={true} /></> : returnCodeInterpretation || (noOutputExpected ? "Done" : "(No output)")}</Text></FullWidthRow></MessageResponse> : null;
|
||||
$[17] = backgroundTaskId;
|
||||
$[18] = cwdResetWarning;
|
||||
$[19] = noOutputExpected;
|
||||
@@ -174,7 +175,7 @@ export default function BashToolResultMessage(t0) {
|
||||
}
|
||||
let t11;
|
||||
if ($[26] !== T0 || $[27] !== t10 || $[28] !== t4 || $[29] !== t5 || $[30] !== t6 || $[31] !== t8 || $[32] !== t9) {
|
||||
t11 = <T0 flexDirection={t4}>{t5}{t6}{t8}{t9}{t10}</T0>;
|
||||
t11 = <T0 flexDirection={t4} width="100%">{t5}{t6}{t8}{t9}{t10}</T0>;
|
||||
$[26] = T0;
|
||||
$[27] = t10;
|
||||
$[28] = t4;
|
||||
|
||||
Reference in New Issue
Block a user