refactor: simplify TOML common config handling by removing markers

- Remove COMMON_CONFIG_MARKER_START/END constants
- Simplify config snippet addition/removal logic
- Use natural append/replace approach instead of markers
- Fix unused variable warning
- Improve user experience with cleaner config output
This commit is contained in:
Jason
2025-09-18 22:33:55 +08:00
parent c6e4f3599e
commit 04e81ebbe3
7 changed files with 116 additions and 112 deletions

View File

@@ -26,8 +26,8 @@ export function AppSwitcher({ activeApp, onSwitch }: AppSwitcherProps) {
<ClaudeIcon
size={16}
className={
activeApp === "claude"
? "text-[#D97757] dark:text-[#D97757] transition-colors duration-200"
activeApp === "claude"
? "text-[#D97757] dark:text-[#D97757] transition-colors duration-200"
: "text-gray-500 dark:text-gray-400 group-hover:text-[#D97757] dark:group-hover:text-[#D97757] transition-colors duration-200"
}
/>

View File

@@ -62,7 +62,7 @@ const JsonEditor: React.FC<JsonEditorProps> = ({
return diagnostics;
}),
[showValidation]
[showValidation],
);
useEffect(() => {

View File

@@ -128,25 +128,26 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
const [settingsConfigError, setSettingsConfigError] = useState("");
// 用于跟踪是否正在通过通用配置更新
const isUpdatingFromCommonConfig = useRef(false);
// Codex 通用配置状态
const [useCodexCommonConfig, setUseCodexCommonConfig] = useState(false);
const [codexCommonConfigSnippet, setCodexCommonConfigSnippetState] = useState<string>(() => {
if (typeof window === "undefined") {
return DEFAULT_CODEX_COMMON_CONFIG_SNIPPET;
}
try {
const stored = window.localStorage.getItem(
CODEX_COMMON_CONFIG_STORAGE_KEY,
);
if (stored && stored.trim()) {
return stored;
const [codexCommonConfigSnippet, setCodexCommonConfigSnippetState] =
useState<string>(() => {
if (typeof window === "undefined") {
return DEFAULT_CODEX_COMMON_CONFIG_SNIPPET;
}
} catch {
// ignore localStorage 读取失败
}
return DEFAULT_CODEX_COMMON_CONFIG_SNIPPET;
});
try {
const stored = window.localStorage.getItem(
CODEX_COMMON_CONFIG_STORAGE_KEY,
);
if (stored && stored.trim()) {
return stored;
}
} catch {
// ignore localStorage 读取失败
}
return DEFAULT_CODEX_COMMON_CONFIG_SNIPPET;
});
const [codexCommonConfigError, setCodexCommonConfigError] = useState("");
const isUpdatingFromCodexCommonConfig = useRef(false);
// -1 表示自定义null 表示未选择,>= 0 表示预设索引
@@ -217,7 +218,11 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
useEffect(() => {
if (initialData) {
if (!isCodex) {
const configString = JSON.stringify(initialData.settingsConfig, null, 2);
const configString = JSON.stringify(
initialData.settingsConfig,
null,
2,
);
const hasCommon = hasCommonConfigSnippet(
configString,
commonConfigSnippet,
@@ -235,7 +240,9 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
};
if (config.env) {
setClaudeModel(config.env.ANTHROPIC_MODEL || "");
setClaudeSmallFastModel(config.env.ANTHROPIC_SMALL_FAST_MODEL || "");
setClaudeSmallFastModel(
config.env.ANTHROPIC_SMALL_FAST_MODEL || "",
);
setBaseUrl(config.env.ANTHROPIC_BASE_URL || ""); // 初始化基础 URL
// 初始化 Kimi 模型选择
@@ -254,7 +261,13 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
setUseCodexCommonConfig(hasCommon);
}
}
}, [initialData, commonConfigSnippet, codexCommonConfigSnippet, isCodex, codexConfig]);
}, [
initialData,
commonConfigSnippet,
codexCommonConfigSnippet,
isCodex,
codexConfig,
]);
// 当选择预设变化时,同步类别
useEffect(() => {
@@ -497,7 +510,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
isUpdatingFromCommonConfig.current = false;
}, 0);
}
// 保存通用配置到 localStorage
if (!validationError && typeof window !== "undefined") {
try {
@@ -529,10 +542,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
setBaseUrl(""); // 清空基础 URL
// 同步通用配置状态
const hasCommon = hasCommonConfigSnippet(
configString,
commonConfigSnippet,
);
const hasCommon = hasCommonConfigSnippet(configString, commonConfigSnippet);
setUseCommonConfig(hasCommon);
setCommonConfigError("");
@@ -643,10 +653,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
updateSettingsConfigValue(configString);
// 同步通用配置开关
const hasCommon = hasCommonConfigSnippet(
configString,
commonConfigSnippet,
);
const hasCommon = hasCommonConfigSnippet(configString, commonConfigSnippet);
setUseCommonConfig(hasCommon);
};
@@ -681,11 +688,12 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
// Codex: 处理通用配置开关
const handleCodexCommonConfigToggle = (checked: boolean) => {
const { updatedConfig, error: snippetError } = updateTomlCommonConfigSnippet(
codexConfig,
codexCommonConfigSnippet,
checked,
);
const { updatedConfig, error: snippetError } =
updateTomlCommonConfigSnippet(
codexConfig,
codexCommonConfigSnippet,
checked,
);
if (snippetError) {
setCodexCommonConfigError(snippetError);
@@ -753,10 +761,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
// 保存 Codex 通用配置到 localStorage
if (typeof window !== "undefined") {
try {
window.localStorage.setItem(
CODEX_COMMON_CONFIG_STORAGE_KEY,
value,
);
window.localStorage.setItem(CODEX_COMMON_CONFIG_STORAGE_KEY, value);
} catch {
// ignore localStorage 写入失败
}
@@ -1177,7 +1182,9 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
useCommonConfig={useCodexCommonConfig}
onCommonConfigToggle={handleCodexCommonConfigToggle}
commonConfigSnippet={codexCommonConfigSnippet}
onCommonConfigSnippetChange={handleCodexCommonConfigSnippetChange}
onCommonConfigSnippetChange={
handleCodexCommonConfigSnippetChange
}
commonConfigError={codexCommonConfigError}
authError={codexAuthError}
/>

View File

@@ -60,7 +60,7 @@ const ClaudeConfigEditor: React.FC<ClaudeConfigEditorProps> = ({
// 支持按下 ESC 关闭弹窗
useEffect(() => {
if (!isCommonConfigModalOpen) return;
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === "Escape") {
e.preventDefault();
@@ -120,15 +120,13 @@ const ClaudeConfigEditor: React.FC<ClaudeConfigEditorProps> = ({
rows={12}
/>
{configError && (
<p className="text-xs text-red-500 dark:text-red-400">
{configError}
</p>
<p className="text-xs text-red-500 dark:text-red-400">{configError}</p>
)}
<p className="text-xs text-gray-500 dark:text-gray-400">
Claude Code settings.json
</p>
{isCommonConfigModalOpen && (
<div
<div
className="fixed inset-0 z-50 flex items-center justify-center"
onMouseDown={(e) => {
if (e.target === e.currentTarget) closeModal();
@@ -136,7 +134,7 @@ const ClaudeConfigEditor: React.FC<ClaudeConfigEditorProps> = ({
>
{/* Backdrop - 统一背景样式 */}
<div className="absolute inset-0 bg-black/50 dark:bg-black/70 backdrop-blur-sm" />
{/* Modal - 统一窗口样式 */}
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-lg max-w-2xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
{/* Header - 统一标题栏样式 */}
@@ -153,7 +151,7 @@ const ClaudeConfigEditor: React.FC<ClaudeConfigEditorProps> = ({
<X size={18} />
</button>
</div>
{/* Content - 统一内容区域样式 */}
<div className="flex-1 overflow-auto p-6 space-y-4">
<p className="text-sm text-gray-500 dark:text-gray-400">
@@ -171,7 +169,7 @@ const ClaudeConfigEditor: React.FC<ClaudeConfigEditorProps> = ({
</p>
)}
</div>
{/* Footer - 统一底部按钮样式 */}
<div className="flex items-center justify-end gap-3 p-6 border-t border-gray-200 dark:border-gray-800 bg-gray-100 dark:bg-gray-800">
<button

View File

@@ -39,7 +39,7 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
// 支持按下 ESC 关闭弹窗
useEffect(() => {
if (!isCommonConfigModalOpen) return;
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === "Escape") {
e.preventDefault();
@@ -97,9 +97,7 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
data-enable-grammarly="false"
/>
{authError && (
<p className="text-xs text-red-500 dark:text-red-400">
{authError}
</p>
<p className="text-xs text-red-500 dark:text-red-400">{authError}</p>
)}
<p className="text-xs text-gray-500 dark:text-gray-400">
Codex auth.json
@@ -161,7 +159,7 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
</div>
{isCommonConfigModalOpen && (
<div
<div
className="fixed inset-0 z-50 flex items-center justify-center"
onMouseDown={(e) => {
if (e.target === e.currentTarget) closeModal();
@@ -169,7 +167,7 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
>
{/* Backdrop - 统一背景样式 */}
<div className="absolute inset-0 bg-black/50 dark:bg-black/70 backdrop-blur-sm" />
{/* Modal - 统一窗口样式 */}
<div className="relative bg-white dark:bg-gray-900 rounded-xl shadow-lg max-w-2xl w-full mx-4 max-h-[90vh] overflow-hidden flex flex-col">
{/* Header - 统一标题栏样式 */}
@@ -186,7 +184,7 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
<X size={18} />
</button>
</div>
{/* Content - 统一内容区域样式 */}
<div className="flex-1 overflow-auto p-6 space-y-4">
<p className="text-sm text-gray-500 dark:text-gray-400">
@@ -194,7 +192,9 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
</p>
<textarea
value={commonConfigSnippet}
onChange={(e) => handleCommonConfigSnippetChange(e.target.value)}
onChange={(e) =>
handleCommonConfigSnippetChange(e.target.value)
}
placeholder={`# Common Codex config
# Add your common TOML configuration here`}
rows={12}
@@ -215,7 +215,7 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
</p>
)}
</div>
{/* Footer - 统一底部按钮样式 */}
<div className="flex items-center justify-end gap-3 p-6 border-t border-gray-200 dark:border-gray-800 bg-gray-100 dark:bg-gray-800">
<button