fix: animate tool paths in sorted chat mode
Adds animated reveals for file path tool descriptions Keeps sorted mode tool animations working without extra chat gaps Preserves file icons, truncation, and click behavior
This commit is contained in:
@@ -700,6 +700,7 @@ const TurnBlock = React.memo(({
|
|||||||
const isFirstAssistant = assistantIndex === 0;
|
const isFirstAssistant = assistantIndex === 0;
|
||||||
const isLastAssistant = assistantIndex === visibleAssistantMessages.length - 1;
|
const isLastAssistant = assistantIndex === visibleAssistantMessages.length - 1;
|
||||||
const isActivityOwner = Boolean(activityOwnerMessageId) && message.info.id === activityOwnerMessageId;
|
const isActivityOwner = Boolean(activityOwnerMessageId) && message.info.id === activityOwnerMessageId;
|
||||||
|
const hasAnchoredActivitySegment = visibleActivitySegments.some((segment) => segment.anchorMessageId === message.info.id);
|
||||||
const shouldAttachFullTurnContext = chatRenderMode === 'sorted'
|
const shouldAttachFullTurnContext = chatRenderMode === 'sorted'
|
||||||
? isAssistantMessage
|
? isAssistantMessage
|
||||||
: (isActivityOwner || isFirstAssistant || isLastAssistant);
|
: (isActivityOwner || isFirstAssistant || isLastAssistant);
|
||||||
@@ -722,7 +723,11 @@ const TurnBlock = React.memo(({
|
|||||||
activityOwnerMessageId,
|
activityOwnerMessageId,
|
||||||
isFirstAssistantInTurn: isFirstAssistant,
|
isFirstAssistantInTurn: isFirstAssistant,
|
||||||
isLastAssistantInTurn: isLastAssistant,
|
isLastAssistantInTurn: isLastAssistant,
|
||||||
isWorking: isLastTurn && sessionIsWorking && message.info.id === streamingAssistantMessageId,
|
isWorking: isLastTurn && sessionIsWorking && (
|
||||||
|
chatRenderMode === 'sorted'
|
||||||
|
? hasAnchoredActivitySegment
|
||||||
|
: message.info.id === streamingAssistantMessageId
|
||||||
|
),
|
||||||
hasTools: turn.hasTools,
|
hasTools: turn.hasTools,
|
||||||
hasReasoning: turn.hasReasoning,
|
hasReasoning: turn.hasReasoning,
|
||||||
...(shouldAttachFullTurnContext ? {
|
...(shouldAttachFullTurnContext ? {
|
||||||
@@ -777,6 +782,7 @@ const TurnBlock = React.memo(({
|
|||||||
activeStreamingPhase,
|
activeStreamingPhase,
|
||||||
visibleAssistantMessages,
|
visibleAssistantMessages,
|
||||||
visibleAssistantIds,
|
visibleAssistantIds,
|
||||||
|
visibleActivitySegments,
|
||||||
activityOwnerMessageId,
|
activityOwnerMessageId,
|
||||||
shouldAnimateUserMessage,
|
shouldAnimateUserMessage,
|
||||||
onUserAnimationConsumed,
|
onUserAnimationConsumed,
|
||||||
|
|||||||
@@ -242,18 +242,19 @@ const getRelativePathFromDirectory = (filePath: string, currentDirectory: string
|
|||||||
return normalizedPath;
|
return normalizedPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderReadFilePath = (displayPath: string) => {
|
const renderReadFilePath = (displayPath: string, animate = true) => {
|
||||||
const lastSlash = displayPath.lastIndexOf('/');
|
const lastSlash = displayPath.lastIndexOf('/');
|
||||||
|
|
||||||
if (lastSlash === -1) {
|
if (lastSlash === -1) {
|
||||||
return (
|
return (
|
||||||
<span
|
<Text
|
||||||
|
variant={animate ? 'generate-effect' : 'static'}
|
||||||
className="min-w-0 flex-1 truncate whitespace-nowrap typography-meta leading-5"
|
className="min-w-0 flex-1 truncate whitespace-nowrap typography-meta leading-5"
|
||||||
style={{ color: 'var(--tools-title)' }}
|
style={{ color: 'var(--tools-title)' }}
|
||||||
title={displayPath}
|
title={displayPath}
|
||||||
>
|
>
|
||||||
{displayPath}
|
{displayPath}
|
||||||
</span>
|
</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +278,13 @@ const renderReadFilePath = (displayPath: string) => {
|
|||||||
{displayDir}
|
{displayDir}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-shrink-0" style={{ color: 'var(--tools-description)' }}>/</span>
|
<span className="flex-shrink-0" style={{ color: 'var(--tools-description)' }}>/</span>
|
||||||
<span className="flex-shrink-0" style={{ color: 'var(--tools-title)' }}>{name}</span>
|
<Text
|
||||||
|
variant={animate ? 'generate-effect' : 'static'}
|
||||||
|
className="flex-shrink-0"
|
||||||
|
style={{ color: 'var(--tools-title)' }}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</Text>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -682,7 +689,7 @@ const StaticToolRowInner: React.FC<{
|
|||||||
title={entry.offset ? `${entry.displayPath}:${entry.offset}` : entry.displayPath}
|
title={entry.offset ? `${entry.displayPath}:${entry.offset}` : entry.displayPath}
|
||||||
>
|
>
|
||||||
{showToolFileIcons ? <FileTypeIcon filePath={entry.path} className="h-3.5 w-3.5" /> : null}
|
{showToolFileIcons ? <FileTypeIcon filePath={entry.path} className="h-3.5 w-3.5" /> : null}
|
||||||
{renderReadFilePath(entry.displayPath)}
|
{renderReadFilePath(entry.displayPath, animateTailText)}
|
||||||
</button>
|
</button>
|
||||||
))
|
))
|
||||||
: null}
|
: null}
|
||||||
|
|||||||
@@ -1359,20 +1359,20 @@ const renderPathLikeGitChanges = (path: string, grow = true) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderAnimatedPathWithIcon = (path: string, _animate = true, grow = true, showFileIcons = true) => {
|
const renderAnimatedPathWithIcon = (path: string, animate = true, grow = true, showFileIcons = true) => {
|
||||||
void _animate;
|
|
||||||
const lastSlash = path.lastIndexOf('/');
|
const lastSlash = path.lastIndexOf('/');
|
||||||
|
|
||||||
if (lastSlash === -1) {
|
if (lastSlash === -1) {
|
||||||
return (
|
return (
|
||||||
<span className={cn('min-w-0 inline-flex items-center gap-1 overflow-hidden', grow && 'flex-1')} title={path}>
|
<span className={cn('min-w-0 inline-flex items-center gap-1 overflow-hidden', grow && 'flex-1')} title={path}>
|
||||||
{showFileIcons ? <FileTypeIcon filePath={path} className="h-3.5 w-3.5 flex-shrink-0" /> : null}
|
{showFileIcons ? <FileTypeIcon filePath={path} className="h-3.5 w-3.5 flex-shrink-0" /> : null}
|
||||||
<span
|
<Text
|
||||||
|
variant={animate ? 'generate-effect' : 'static'}
|
||||||
className={cn('min-w-0 truncate whitespace-nowrap typography-meta', grow && 'flex-1')}
|
className={cn('min-w-0 truncate whitespace-nowrap typography-meta', grow && 'flex-1')}
|
||||||
style={{ color: 'var(--tools-title)' }}
|
style={{ color: 'var(--tools-title)' }}
|
||||||
>
|
>
|
||||||
{path}
|
{path}
|
||||||
</span>
|
</Text>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1399,9 +1399,13 @@ const renderAnimatedPathWithIcon = (path: string, _animate = true, grow = true,
|
|||||||
{displayDir}
|
{displayDir}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-shrink-0" style={{ color: 'var(--tools-description)' }}>/</span>
|
<span className="flex-shrink-0" style={{ color: 'var(--tools-description)' }}>/</span>
|
||||||
<span className="flex-shrink-0" style={{ color: 'var(--tools-title)' }}>
|
<Text
|
||||||
|
variant={animate ? 'generate-effect' : 'static'}
|
||||||
|
className="flex-shrink-0"
|
||||||
|
style={{ color: 'var(--tools-title)' }}
|
||||||
|
>
|
||||||
{name}
|
{name}
|
||||||
</span>
|
</Text>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user