diff --git a/src/features/settings/__tests__/dialog.test.tsx b/src/features/settings/__tests__/dialog.test.tsx
index f33d9d401..a4bc899e7 100644
--- a/src/features/settings/__tests__/dialog.test.tsx
+++ b/src/features/settings/__tests__/dialog.test.tsx
@@ -24,8 +24,9 @@ import { registerAction, executeAction } from "@/platform/actions";
import { useProject } from "@/platform/project";
import { useKeymap } from "@/platform/keymap";
import { ContextMenuHost } from "@/ui";
+import { PageContext, useSetting } from "../components/context";
import { DEFAULT_SETTINGS, setAt } from "../model/schema";
-import { stage, useSettingsDialog } from "../model/staging";
+import { openSettings, stage, useSettingsDialog } from "../model/staging";
import { SettingsDialog } from "../dialog/SettingsDialog";
import { activate } from "..";
import { MessagesHost } from "@/workbench/messages";
@@ -271,6 +272,37 @@ describe("Settings dialog", () => {
});
});
+ it("keeps object settings stable when child keys are staged (HTTP Proxy)", async () => {
+ const seen: Array<{ mode: string; host: string }> = [];
+ function Probe() {
+ const [proxy] = useSetting<{ mode: string; host: string }>("proxy", "global");
+ seen.push(proxy);
+ return ;
+ }
+ openSettings("general.httpProxy");
+ const view = render(
+
+
+ ,
+ );
+ expect(screen.getByTestId("proxy")).toHaveTextContent("auto:");
+ act(() => {
+ stage("general.httpProxy", "global", "proxy.mode", "manual");
+ stage("general.httpProxy", "global", "proxy.host", "127.0.0.1");
+ });
+ expect(screen.getByTestId("proxy")).toHaveTextContent("manual:127.0.0.1");
+ expect(seen.at(-1)).toMatchObject({ mode: "manual", host: "127.0.0.1" });
+ view.unmount();
+
+ const dialog = await openDialog("general.httpProxy");
+ fireEvent.click(within(dialog).getByRole("radio", { name: "Manual proxy configuration" }));
+ expect(within(dialog).getByRole("radio", { name: "Manual proxy configuration" })).toBeChecked();
+ fireEvent.change(within(dialog).getByLabelText("Host name"), { target: { value: "127.0.0.1" } });
+ expect(within(dialog).getByLabelText("Host name")).toHaveValue("127.0.0.1");
+ fireEvent.click(within(dialog).getByRole("radio", { name: "No proxy" }));
+ expect(within(dialog).getByRole("radio", { name: "No proxy" })).toBeChecked();
+ });
+
it("survives invalid settings values", async () => {
act(() =>
useProject.setState({
diff --git a/src/features/settings/components/context.ts b/src/features/settings/components/context.ts
index 9e762f663..d0a3fc690 100644
--- a/src/features/settings/components/context.ts
+++ b/src/features/settings/components/context.ts
@@ -19,7 +19,7 @@ export function usePageContext(): PageContextValue {
export function useSetting(key: string, scopeOverride?: Scope): [T, (value: T) => void] {
const { pageId, scope: pageScope } = usePageContext();
const scope = scopeOverride ?? pageScope;
- const value = useSettingsDialog((s) => stagedValue(s, scope, key)) as T;
+ const value = useStagedValue(scope, key) as T;
const set = useCallback((v: T) => stage(pageId, scope, key, v), [pageId, scope, key]);
return [value, set];
}