Skip to content

feat: add autoExpandDiffs setting to auto-expand diffs in chat messages#11316

Draft
roomote-v0[bot] wants to merge 1 commit intomainfrom
feature/auto-expand-diffs
Draft

feat: add autoExpandDiffs setting to auto-expand diffs in chat messages#11316
roomote-v0[bot] wants to merge 1 commit intomainfrom
feature/auto-expand-diffs

Conversation

@roomote-v0
Copy link
Copy Markdown
Contributor

@roomote-v0 roomote-v0 bot commented Feb 8, 2026

Related GitHub Issue

Closes: #10955

Description

This PR attempts to address Issue #10955. Feedback and guidance are welcome.

Adds a new boolean setting autoExpandDiffs (default: false) under Settings > UI. When enabled, file edit diffs in chat messages (e.g. "Roo wants to edit this file") are automatically expanded instead of requiring a click on the collapsed filename bar.

Implementation details:

  • Types layer (packages/types): Added autoExpandDiffs to globalSettingsSchema and the ExtensionState Pick type so it flows through the state system.
  • Context (ExtensionStateContext): Added default value (false) and hydration handling.
  • ChatView: Added a useEffect that watches groupedMessages and auto-expands any diff tool messages (editedExistingFile, appliedDiff, newFileCreated, insertContent, searchAndReplace, batchDiffApproval) when the setting is enabled. Only new (untracked) messages are expanded to avoid fighting with manual user toggles.
  • UISettings: Added a checkbox toggle for the new setting.
  • SettingsView: Wired the setting through cachedState for the save/discard workflow.
  • i18n: Added English translation strings.

The CodeAccordion component already enforces a max-h-[300px] (300px) limit with overflow-y: auto, so auto-expanded diffs will not take over the chat view -- anything taller than 300px gets a scrollbar.

Test Procedure

  • All existing UISettings tests updated and passing (4/4).
  • SettingsView change-detection and unsaved-changes tests updated and passing (3 passed, 5 skipped -- skipped tests are pre-existing).
  • All lint checks pass across the monorepo.
  • All type checks pass across the monorepo.

Manual testing steps:

  1. Open Settings > UI tab
  2. Enable "Auto-expand diffs in chat messages"
  3. Save settings
  4. Start a task that edits files
  5. Observe that diff blocks are automatically expanded in the chat

Pre-Submission Checklist

  • Issue Linked: This PR is linked to an approved GitHub Issue.
  • Scope: My changes are focused on the linked issue.
  • Self-Review: I have performed a thorough self-review of my code.
  • Testing: Updated tests have been added to cover my changes.
  • Documentation Impact: No documentation updates needed.
  • Contribution Guidelines: I have read and agree to the Contributor Guidelines.

Documentation Updates

No documentation updates needed. The setting is exposed in Settings > UI with a clear label and description.

@roomote-v0
Copy link
Copy Markdown
Contributor Author

roomote-v0 bot commented Feb 8, 2026

Rooviewer Clock   See task

Reviewed. The settings plumbing, types, UI toggle, and i18n look correct. Found 2 issues in the auto-expand useEffect in ChatView.tsx:

  • expandedRows in the dependency array causes unnecessary re-executions (every user expand/collapse re-iterates all messages with JSON.parse) and a double-run cycle on auto-expand. Use the functional updater of setExpandedRows and drop expandedRows from deps.
  • Auto-expansion triggers the existing expansion-tracking effect (lines 509-529) which disables stickyFollowRef (auto-scroll). During an active task, each new diff auto-expand stops the chat from scrolling to new messages.

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

Comment on lines +537 to +566
useEffect(() => {
if (!autoExpandDiffs) {
return
}

const newExpansions: Record<number, boolean> = {}

for (const msg of modifiedMessages) {
// Skip messages already tracked in expandedRows
if (expandedRows[msg.ts] !== undefined) {
continue
}

// Check if this message contains a diff tool
if (msg.text) {
try {
const tool = JSON.parse(msg.text)
if (tool.tool && DIFF_TOOL_TYPES.has(tool.tool)) {
newExpansions[msg.ts] = true
}
} catch {
// Not valid JSON, skip
}
}
}

if (Object.keys(newExpansions).length > 0) {
setExpandedRows((prev) => ({ ...prev, ...newExpansions }))
}
}, [modifiedMessages, autoExpandDiffs, expandedRows, DIFF_TOOL_TYPES])
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Including expandedRows in the dependency array here means this effect re-runs on every expansion/collapse (user or auto), iterating all modifiedMessages and JSON.parse-ing each one. It also causes a double execution when it auto-expands: the setExpandedRows call updates expandedRows, which re-triggers the effect (the second run is a no-op but still wasteful). You can fix both problems by moving the logic into the functional updater of setExpandedRows and dropping expandedRows from deps:

Suggested change
useEffect(() => {
if (!autoExpandDiffs) {
return
}
const newExpansions: Record<number, boolean> = {}
for (const msg of modifiedMessages) {
// Skip messages already tracked in expandedRows
if (expandedRows[msg.ts] !== undefined) {
continue
}
// Check if this message contains a diff tool
if (msg.text) {
try {
const tool = JSON.parse(msg.text)
if (tool.tool && DIFF_TOOL_TYPES.has(tool.tool)) {
newExpansions[msg.ts] = true
}
} catch {
// Not valid JSON, skip
}
}
}
if (Object.keys(newExpansions).length > 0) {
setExpandedRows((prev) => ({ ...prev, ...newExpansions }))
}
}, [modifiedMessages, autoExpandDiffs, expandedRows, DIFF_TOOL_TYPES])
useEffect(() => {
if (!autoExpandDiffs) {
return
}
setExpandedRows((prev) => {
const newExpansions: Record<number, boolean> = {}
for (const msg of modifiedMessages) {
if (prev[msg.ts] !== undefined) {
continue
}
if (msg.text) {
try {
const tool = JSON.parse(msg.text)
if (tool.tool && DIFF_TOOL_TYPES.has(tool.tool)) {
newExpansions[msg.ts] = true
}
} catch {
// Not valid JSON, skip
}
}
}
if (Object.keys(newExpansions).length > 0) {
return { ...prev, ...newExpansions }
}
return prev
})
}, [modifiedMessages, autoExpandDiffs, DIFF_TOOL_TYPES])

Fix it with Roo Code or mention @roomote and request a fix.

Comment on lines +537 to +566
useEffect(() => {
if (!autoExpandDiffs) {
return
}

const newExpansions: Record<number, boolean> = {}

for (const msg of modifiedMessages) {
// Skip messages already tracked in expandedRows
if (expandedRows[msg.ts] !== undefined) {
continue
}

// Check if this message contains a diff tool
if (msg.text) {
try {
const tool = JSON.parse(msg.text)
if (tool.tool && DIFF_TOOL_TYPES.has(tool.tool)) {
newExpansions[msg.ts] = true
}
} catch {
// Not valid JSON, skip
}
}
}

if (Object.keys(newExpansions).length > 0) {
setExpandedRows((prev) => ({ ...prev, ...newExpansions }))
}
}, [modifiedMessages, autoExpandDiffs, expandedRows, DIFF_TOOL_TYPES])
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When this effect auto-expands diffs via setExpandedRows, the existing effect at lines 509-529 will detect those transitions (from undefined to true) and set stickyFollowRef.current = false, disabling auto-scroll. It cannot distinguish between user-initiated and programmatic expansions. During an active task with autoExpandDiffs enabled, each new diff message gets auto-expanded, triggers that detection, and disables auto-scroll -- the user has to manually scroll to see subsequent messages, which undermines the purpose of this feature. Consider guarding against this by setting a ref flag (e.g. isAutoExpandingRef.current = true) before calling setExpandedRows here, and checking it in the expansion-tracking effect to skip the sticky-follow disable.

Fix it with Roo Code or mention @roomote and request a fix.

Adds a new boolean setting "autoExpandDiffs" (default: false) under
Settings > UI. When enabled, file edit diffs in chat messages are
automatically expanded instead of requiring a click on the collapsed
filename bar.

The CodeAccordion component already enforces a 300px max height with
scrollbar, so auto-expanded diffs will not overwhelm the chat view.

Changes:
- packages/types: add autoExpandDiffs to GlobalSettings schema and ExtensionState
- webview-ui context: add default and hydration for autoExpandDiffs
- ChatView: add useEffect that auto-expands diff tool messages when setting is on
- UISettings: add checkbox toggle for the new setting
- SettingsView: wire the new setting through cached state
- i18n: add English translation strings
- Tests: update test fixtures for change-detection, unsaved-changes, UISettings

Closes #10955
@roomote-v0 roomote-v0 bot force-pushed the feature/auto-expand-diffs branch from d1bddd3 to 0ac5f16 Compare April 19, 2026 19:53
@roomote-v0 roomote-v0 bot changed the title feat: add setting to auto-expand diffs in chat messages feat: add autoExpandDiffs setting to auto-expand diffs in chat messages Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Add setting to auto-expand diffs in "Roo wants to edit this file" chat messages

1 participant