From 11f1ef33e45f8a856c45c8b2d8d611b379ffcd58 Mon Sep 17 00:00:00 2001 From: JIA-ss <62920066+JIA-ss@users.noreply.github.com> Date: Sun, 15 Feb 2026 22:10:40 +0800 Subject: [PATCH] feat(ui): add quick config toggles to Claude config editor (#1012) Add 3 quick-toggle checkboxes above the JSON editor in Claude provider settings: - Hide AI Attribution (sets attribution.commit/pr to empty string) - Extended Thinking (sets alwaysThinkingEnabled to true) - Teammates Mode (sets env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS to "1") Uses local state to keep toggles and JsonEditor in sync without triggering ProviderForm re-renders. Includes i18n for zh/en/ja. Co-authored-by: Jason --- .../providers/forms/CommonConfigEditor.tsx | 112 +++++++++++++++++- src/i18n/locales/en.json | 5 +- src/i18n/locales/ja.json | 5 +- src/i18n/locales/zh.json | 5 +- 4 files changed, 121 insertions(+), 6 deletions(-) diff --git a/src/components/providers/forms/CommonConfigEditor.tsx b/src/components/providers/forms/CommonConfigEditor.tsx index 04d175569..b81bea564 100644 --- a/src/components/providers/forms/CommonConfigEditor.tsx +++ b/src/components/providers/forms/CommonConfigEditor.tsx @@ -1,5 +1,5 @@ import { useTranslation } from "react-i18next"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useCallback, useMemo } from "react"; import { FullScreenPanel } from "@/components/common/FullScreenPanel"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; @@ -53,6 +53,81 @@ export function CommonConfigEditor({ return () => observer.disconnect(); }, []); + // Mirror value prop to local state so checkbox toggles and JsonEditor stay in sync + // (parent uses form.getValues which doesn't trigger re-renders) + const [localValue, setLocalValue] = useState(value); + + useEffect(() => { + setLocalValue(value); + }, [value]); + + const handleLocalChange = useCallback( + (newValue: string) => { + setLocalValue(newValue); + onChange(newValue); + }, + [onChange], + ); + + const toggleStates = useMemo(() => { + try { + const config = JSON.parse(localValue); + return { + hideAttribution: + config?.attribution?.commit === "" && config?.attribution?.pr === "", + alwaysThinking: config?.alwaysThinkingEnabled === true, + teammates: + config?.env?.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === "1" || + config?.env?.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS === 1, + }; + } catch { + return { + hideAttribution: false, + alwaysThinking: false, + teammates: false, + }; + } + }, [localValue]); + + const handleToggle = useCallback( + (toggleKey: string, checked: boolean) => { + try { + const config = JSON.parse(localValue || "{}"); + + switch (toggleKey) { + case "hideAttribution": + if (checked) { + config.attribution = { commit: "", pr: "" }; + } else { + delete config.attribution; + } + break; + case "alwaysThinking": + if (checked) { + config.alwaysThinkingEnabled = true; + } else { + delete config.alwaysThinkingEnabled; + } + break; + case "teammates": + if (!config.env) config.env = {}; + if (checked) { + config.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = "1"; + } else { + delete config.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS; + if (Object.keys(config.env).length === 0) delete config.env; + } + break; + } + + handleLocalChange(JSON.stringify(config, null, 2)); + } catch { + // Don't modify if JSON is invalid + } + }, + [localValue, handleLocalChange], + ); + return ( <>
@@ -91,9 +166,40 @@ export function CommonConfigEditor({ {commonConfigError}

)} +
+ + + +