Roo-Code/webview-ui/src/components/settings/UISettings.tsx
Roo Code 0ac5f16f87
Some checks failed
Preview roocode.com / check-secrets (push) Has been cancelled
Preview roocode.com / preview (push) Has been cancelled
feat: add autoExpandDiffs setting to auto-expand diffs in chat messages
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
2026-04-19 19:51:58 +00:00

122 lines
4.1 KiB
TypeScript

import { HTMLAttributes, useMemo } from "react"
import { useAppTranslation } from "@/i18n/TranslationContext"
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
import { telemetryClient } from "@/utils/TelemetryClient"
import { SetCachedStateField } from "./types"
import { SectionHeader } from "./SectionHeader"
import { Section } from "./Section"
import { SearchableSetting } from "./SearchableSetting"
import { ExtensionStateContextType } from "@/context/ExtensionStateContext"
interface UISettingsProps extends HTMLAttributes<HTMLDivElement> {
reasoningBlockCollapsed: boolean
autoExpandDiffs: boolean
enterBehavior: "send" | "newline"
setCachedStateField: SetCachedStateField<keyof ExtensionStateContextType>
}
export const UISettings = ({
reasoningBlockCollapsed,
autoExpandDiffs,
enterBehavior,
setCachedStateField,
...props
}: UISettingsProps) => {
const { t } = useAppTranslation()
// Detect platform for dynamic modifier key display
const primaryMod = useMemo(() => {
const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0
return isMac ? "⌘" : "Ctrl"
}, [])
const handleReasoningBlockCollapsedChange = (value: boolean) => {
setCachedStateField("reasoningBlockCollapsed", value)
// Track telemetry event
telemetryClient.capture("ui_settings_collapse_thinking_changed", {
enabled: value,
})
}
const handleAutoExpandDiffsChange = (value: boolean) => {
setCachedStateField("autoExpandDiffs", value)
}
const handleEnterBehaviorChange = (requireCtrlEnter: boolean) => {
const newBehavior = requireCtrlEnter ? "newline" : "send"
setCachedStateField("enterBehavior", newBehavior)
// Track telemetry event
telemetryClient.capture("ui_settings_enter_behavior_changed", {
behavior: newBehavior,
})
}
return (
<div {...props}>
<SectionHeader>{t("settings:sections.ui")}</SectionHeader>
<Section>
<div className="space-y-6">
{/* Collapse Thinking Messages Setting */}
<SearchableSetting
settingId="ui-collapse-thinking"
section="ui"
label={t("settings:ui.collapseThinking.label")}>
<div className="flex flex-col gap-1">
<VSCodeCheckbox
checked={reasoningBlockCollapsed}
onChange={(e: any) => handleReasoningBlockCollapsedChange(e.target.checked)}
data-testid="collapse-thinking-checkbox">
<span className="font-medium">{t("settings:ui.collapseThinking.label")}</span>
</VSCodeCheckbox>
<div className="text-vscode-descriptionForeground text-sm ml-5 mt-1">
{t("settings:ui.collapseThinking.description")}
</div>
</div>
</SearchableSetting>
{/* Auto-Expand Diffs Setting */}
<SearchableSetting
settingId="ui-auto-expand-diffs"
section="ui"
label={t("settings:ui.autoExpandDiffs.label")}>
<div className="flex flex-col gap-1">
<VSCodeCheckbox
checked={autoExpandDiffs}
onChange={(e: any) => handleAutoExpandDiffsChange(e.target.checked)}
data-testid="auto-expand-diffs-checkbox">
<span className="font-medium">{t("settings:ui.autoExpandDiffs.label")}</span>
</VSCodeCheckbox>
<div className="text-vscode-descriptionForeground text-sm ml-5 mt-1">
{t("settings:ui.autoExpandDiffs.description")}
</div>
</div>
</SearchableSetting>
{/* Enter Key Behavior Setting */}
<SearchableSetting
settingId="ui-enter-behavior"
section="ui"
label={t("settings:ui.requireCtrlEnterToSend.label", { primaryMod })}>
<div className="flex flex-col gap-1">
<VSCodeCheckbox
checked={enterBehavior === "newline"}
onChange={(e: any) => handleEnterBehaviorChange(e.target.checked)}
data-testid="enter-behavior-checkbox">
<span className="font-medium">
{t("settings:ui.requireCtrlEnterToSend.label", { primaryMod })}
</span>
</VSCodeCheckbox>
<div className="text-vscode-descriptionForeground text-sm ml-5 mt-1">
{t("settings:ui.requireCtrlEnterToSend.description", { primaryMod })}
</div>
</div>
</SearchableSetting>
</div>
</Section>
</div>
)
}