From e9fdf23fd38404faff2ed841203275a151f70c32 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sun, 27 Jul 2025 14:01:37 +0000 Subject: [PATCH 1/2] feat: Show checkpoint button on all subsequent messages instead of creating new checkpoints - Modified ChatView to track the last checkpoint info - Updated ChatRow to display checkpoint UI on all messages after a checkpoint - Created ChatRowWithCheckpoint wrapper component to handle checkpoint display logic - Removed rendering of checkpoint_saved messages themselves This change improves the UI by showing a persistent checkpoint button on all messages after a checkpoint is created, rather than creating new checkpoint messages after each interaction. --- webview-ui/src/components/chat/ChatRow.tsx | 54 +++++++++++++++++---- webview-ui/src/components/chat/ChatView.tsx | 16 ++++++ 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 4fa921f4435..1c45a68614b 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -60,6 +60,11 @@ interface ChatRowProps { onFollowUpUnmount?: () => void isFollowUpAnswered?: boolean editable?: boolean + lastCheckpointInfo?: { + ts: number + commitHash: string + checkpoint?: Record + } | null } // eslint-disable-next-line @typescript-eslint/no-empty-object-type @@ -74,7 +79,7 @@ const ChatRow = memo( const [chatrow, { height }] = useSize(
- +
, ) @@ -112,9 +117,10 @@ export const ChatRowContent = ({ onBatchFileResponse, isFollowUpAnswered, editable, + lastCheckpointInfo: _lastCheckpointInfo, }: ChatRowContentProps) => { const { t } = useTranslation() - const { mcpServers, alwaysAllowMcp, currentCheckpoint, mode } = useExtensionState() + const { mcpServers, alwaysAllowMcp, currentCheckpoint: _currentCheckpoint, mode } = useExtensionState() const [reasoningCollapsed, setReasoningCollapsed] = useState(true) const [isDiffErrorExpanded, setIsDiffErrorExpanded] = useState(false) const [showCopySuccess, setShowCopySuccess] = useState(false) @@ -1157,14 +1163,8 @@ export const ChatRowContent = ({ case "shell_integration_warning": return case "checkpoint_saved": - return ( - - ) + // Don't render the checkpoint_saved message itself + return null case "condense_context": if (message.partial) { return @@ -1345,4 +1345,38 @@ export const ChatRowContent = ({ return null } } + + // Default return for messages that don't match any case + return null +} + +// Create a wrapper component to handle the checkpoint UI +export const ChatRowWithCheckpoint: React.FC = (props) => { + const { message, lastCheckpointInfo } = props + const { currentCheckpoint } = useExtensionState() + + // Render the regular content + const content = + + // Check if we should show checkpoint UI + const shouldShowCheckpoint = + lastCheckpointInfo && message.ts > lastCheckpointInfo.ts && message.say !== "checkpoint_saved" + + if (shouldShowCheckpoint) { + return ( + <> + {content} +
+ +
+ + ) + } + + return content } diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index efd2db856c0..99c6166d941 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -145,6 +145,20 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + // Find the last checkpoint_saved message + const checkpointMessages = messages.filter((msg) => msg.say === "checkpoint_saved") + if (checkpointMessages.length === 0) return null + + const lastCheckpoint = checkpointMessages[checkpointMessages.length - 1] + return { + ts: lastCheckpoint.ts, + commitHash: lastCheckpoint.text || "", + checkpoint: lastCheckpoint.checkpoint, + } + }, [messages]) + const modifiedMessages = useMemo(() => combineApiRequests(combineCommandSequences(messages.slice(1))), [messages]) // Has to be after api_req_finished are all reduced into api_req_started messages. @@ -1398,6 +1412,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction Date: Wed, 30 Jul 2025 00:03:09 +0000 Subject: [PATCH 2/2] fix: address review feedback - Remove unused lastCheckpointInfo parameter from ChatRowContent - Remove unreachable return null statement - Optimize useMemo performance for lastCheckpointInfo calculation --- webview-ui/src/components/chat/ChatRow.tsx | 6 +----- webview-ui/src/components/chat/ChatView.tsx | 7 +++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 1c45a68614b..17732dd2dbc 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -117,7 +117,6 @@ export const ChatRowContent = ({ onBatchFileResponse, isFollowUpAnswered, editable, - lastCheckpointInfo: _lastCheckpointInfo, }: ChatRowContentProps) => { const { t } = useTranslation() const { mcpServers, alwaysAllowMcp, currentCheckpoint: _currentCheckpoint, mode } = useExtensionState() @@ -1345,9 +1344,6 @@ export const ChatRowContent = ({ return null } } - - // Default return for messages that don't match any case - return null } // Create a wrapper component to handle the checkpoint UI @@ -1356,7 +1352,7 @@ export const ChatRowWithCheckpoint: React.FC = (props) => { const { currentCheckpoint } = useExtensionState() // Render the regular content - const content = + const content = // Check if we should show checkpoint UI const shouldShowCheckpoint = diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 99c6166d941..6563aca5a4c 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -145,10 +145,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction messages.filter((msg) => msg.say === "checkpoint_saved"), [messages]) const lastCheckpointInfo = useMemo(() => { - // Find the last checkpoint_saved message - const checkpointMessages = messages.filter((msg) => msg.say === "checkpoint_saved") if (checkpointMessages.length === 0) return null const lastCheckpoint = checkpointMessages[checkpointMessages.length - 1] @@ -157,7 +156,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction combineApiRequests(combineCommandSequences(messages.slice(1))), [messages])