From c7d12309134eb69765086cc5dfeab0853c1ea3f3 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Thu, 30 Apr 2026 13:56:30 +0000 Subject: [PATCH] feat: add lock API config toggle to Settings providers tab (#12237) Adds a "Use the same API configuration for all modes" checkbox to the Providers section in Settings, making the existing lockApiConfigAcrossModes feature discoverable without needing to find the small lock icon inside the API Configuration popover. - Adds VSCodeCheckbox to SettingsView providers tab bound to cachedState - Sends lockApiConfigAcrossModes message on save (same handler as popover) - Adds i18n strings for the label and description - Adds test coverage for rendering, toggling, and save behavior --- .../src/components/settings/SettingsView.tsx | 19 + .../SettingsView.lockApiConfig.spec.tsx | 361 ++++++++++++++++++ webview-ui/src/i18n/locales/en/settings.json | 2 + 3 files changed, 382 insertions(+) create mode 100644 webview-ui/src/components/settings/__tests__/SettingsView.lockApiConfig.spec.tsx diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 47e087615e3..1d976500e79 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -39,6 +39,8 @@ import { ImageGenerationProvider, } from "@roo-code/types" +import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react" + import { vscode } from "@src/utils/vscode" import { cn } from "@src/lib/utils" import { useAppTranslation } from "@src/i18n/TranslationContext" @@ -203,6 +205,7 @@ const SettingsView = forwardRef(({ onDone, t includeCurrentTime, includeCurrentCost, maxGitStatusFiles, + lockApiConfigAcrossModes, } = cachedState const apiConfiguration = useMemo(() => cachedState.apiConfiguration ?? {}, [cachedState.apiConfiguration]) @@ -430,6 +433,7 @@ const SettingsView = forwardRef(({ onDone, t vscode.postMessage({ type: "upsertApiConfiguration", text: currentApiConfigName, apiConfiguration }) vscode.postMessage({ type: "telemetrySetting", text: telemetrySetting }) vscode.postMessage({ type: "debugSetting", bool: cachedState.debug }) + vscode.postMessage({ type: "lockApiConfigAcrossModes", bool: lockApiConfigAcrossModes ?? false }) setChangeDetected(false) } @@ -766,6 +770,21 @@ const SettingsView = forwardRef(({ onDone, t }) } /> +
+ + setCachedStateField("lockApiConfigAcrossModes", e.target.checked) + } + data-testid="lock-api-config-across-modes-checkbox"> + + {t("settings:providers.lockApiConfigAcrossModes")} + + +
+ {t("settings:providers.lockApiConfigAcrossModesDescription")} +
+
({ vscode: { postMessage: vi.fn() } })) + +vi.mock("../ApiConfigManager", () => ({ + __esModule: true, + default: ({ currentApiConfigName }: any) => ( +
+ Current config: {currentApiConfigName} +
+ ), +})) + +vi.mock("@vscode/webview-ui-toolkit/react", () => ({ + VSCodeButton: ({ children, onClick, appearance, "data-testid": dataTestId }: any) => + appearance === "icon" ? ( + + ) : ( + + ), + VSCodeCheckbox: ({ children, onChange, checked, "data-testid": dataTestId }: any) => ( + + ), + VSCodeTextField: ({ value, onInput, placeholder, "data-testid": dataTestId }: any) => ( + onInput?.({ target: { value: e.target.value } })} + placeholder={placeholder} + data-testid={dataTestId} + /> + ), + VSCodeLink: ({ children, href }: any) => {children}, + VSCodeRadio: ({ value, checked, onChange }: any) => ( + + ), + VSCodeRadioGroup: ({ children, onChange }: any) =>
{children}
, + VSCodeTextArea: ({ value, onChange, rows, className, "data-testid": dataTestId }: any) => ( +