From 451ca949ec80626e9282afb62d049bb88e074cf3 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 3 Sep 2025 15:58:02 +0800 Subject: [PATCH] feat(ui): improve provider configuration UX with custom option - Add explicit "Custom" button in preset selection - Set "Custom" as default selection when adding new provider - Update label from "One-click import" to "Choose configuration type" - Add contextual hints for different configuration modes: - Custom mode: "Manually configure provider, complete configuration required" - Official preset: "Official login, no API Key required" - Other presets: "Use preset configuration, only API Key required" - Remove redundant "(optional)" text from Codex config.toml hint - Improve clarity for users who were confused about adding custom providers --- src/components/ProviderForm.tsx | 95 +++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/src/components/ProviderForm.tsx b/src/components/ProviderForm.tsx index 00881d5..1288f86 100644 --- a/src/components/ProviderForm.tsx +++ b/src/components/ProviderForm.tsx @@ -47,8 +47,9 @@ const ProviderForm: React.FC = ({ const [codexAuth, setCodexAuth] = useState(""); const [codexConfig, setCodexConfig] = useState(""); const [codexApiKey, setCodexApiKey] = useState(""); + // -1 表示自定义,null 表示未选择,>= 0 表示预设索引 const [selectedCodexPreset, setSelectedCodexPreset] = useState( - null, + showPresets && isCodex ? -1 : null, ); // 初始化 Codex 配置 @@ -71,7 +72,10 @@ const ProviderForm: React.FC = ({ }, [isCodex, initialData]); const [error, setError] = useState(""); const [disableCoAuthored, setDisableCoAuthored] = useState(false); - const [selectedPreset, setSelectedPreset] = useState(null); + // -1 表示自定义,null 表示未选择,>= 0 表示预设索引 + const [selectedPreset, setSelectedPreset] = useState( + showPresets ? -1 : null + ); const [apiKey, setApiKey] = useState(""); // 初始化时检查禁用签名状态 @@ -216,6 +220,18 @@ const ProviderForm: React.FC = ({ setDisableCoAuthored(hasCoAuthoredDisabled); }; + // 处理点击自定义按钮 + const handleCustomClick = () => { + setSelectedPreset(-1); + setFormData({ + name: "", + websiteUrl: "", + settingsConfig: "", + }); + setApiKey(""); + setDisableCoAuthored(false); + }; + // Codex: 应用预设 const applyCodexPreset = ( preset: (typeof codexProviderPresets)[0], @@ -237,6 +253,19 @@ const ProviderForm: React.FC = ({ setCodexApiKey(""); }; + // Codex: 处理点击自定义按钮 + const handleCodexCustomClick = () => { + setSelectedCodexPreset(-1); + setFormData({ + name: "", + websiteUrl: "", + settingsConfig: "", + }); + setCodexAuth(""); + setCodexConfig(""); + setCodexApiKey(""); + }; + // 处理 API Key 输入并自动更新配置 const handleApiKeyChange = (key: string) => { setApiKey(key); @@ -244,7 +273,7 @@ const ProviderForm: React.FC = ({ const configString = setApiKeyInConfig( formData.settingsConfig, key.trim(), - { createIfMissing: selectedPreset !== null }, + { createIfMissing: selectedPreset !== null && selectedPreset !== -1 }, ); // 更新表单配置 @@ -271,12 +300,15 @@ const ProviderForm: React.FC = ({ }; // 根据当前配置决定是否展示 API Key 输入框 + // 自定义模式(-1)不显示独立的 API Key 输入框 const showApiKey = - selectedPreset !== null || hasApiKeyField(formData.settingsConfig); + (selectedPreset !== null && selectedPreset !== -1) || + (!showPresets && hasApiKeyField(formData.settingsConfig)); // 判断当前选中的预设是否是官方 const isOfficialPreset = selectedPreset !== null && + selectedPreset >= 0 && providerPresets[selectedPreset]?.isOfficial === true; // Codex: 控制显示 API Key 与官方标记 @@ -288,10 +320,13 @@ const ProviderForm: React.FC = ({ return ""; } }; + // 自定义模式(-1)不显示独立的 API Key 输入框 const showCodexApiKey = - selectedCodexPreset !== null || getCodexAuthApiKey(codexAuth) !== ""; + (selectedCodexPreset !== null && selectedCodexPreset !== -1) || + (!showPresets && getCodexAuthApiKey(codexAuth) !== ""); const isCodexOfficialPreset = selectedCodexPreset !== null && + selectedCodexPreset >= 0 && codexProviderPresets[selectedCodexPreset]?.isOfficial === true; // 初始时从配置中同步 API Key(编辑模式) @@ -347,8 +382,17 @@ const ProviderForm: React.FC = ({ {showPresets && !isCodex && (
- +
+ {providerPresets.map((preset, index) => { return (
+ {selectedPreset === -1 && ( + + 手动配置供应商,需要填写完整的配置信息 + + )} + {selectedPreset !== -1 && selectedPreset !== null && ( + + {isOfficialPreset + ? "Claude 官方登录,不需要填写 API Key" + : "使用预设配置,只需填写 API Key"} + + )}
)} {showPresets && isCodex && (
- +
+ {codexProviderPresets.map((preset, index) => ( ))}
+ {selectedCodexPreset === -1 && ( + + 手动配置供应商,需要填写完整的配置信息 + + )} + {selectedCodexPreset !== -1 && selectedCodexPreset !== null && ( + + {isCodexOfficialPreset + ? "Codex 官方登录,不需要填写 API Key" + : "使用预设配置,只需填写 API Key"} + + )}
)} @@ -448,7 +525,7 @@ const ProviderForm: React.FC = ({ } disabled={isCodexOfficialPreset} required={ - selectedCodexPreset !== null && !isCodexOfficialPreset + selectedCodexPreset !== null && selectedCodexPreset >= 0 && !isCodexOfficialPreset } autoComplete="off" style={ @@ -521,7 +598,7 @@ const ProviderForm: React.FC = ({ style={{ fontFamily: "monospace", fontSize: "14px" }} /> - Codex config.toml 配置内容(可留空) + Codex config.toml 配置内容