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
This commit is contained in:
Jason
2025-09-03 15:58:02 +08:00
parent a9ff8ce01c
commit 451ca949ec

View File

@@ -47,8 +47,9 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
const [codexAuth, setCodexAuth] = useState("");
const [codexConfig, setCodexConfig] = useState("");
const [codexApiKey, setCodexApiKey] = useState("");
// -1 表示自定义null 表示未选择,>= 0 表示预设索引
const [selectedCodexPreset, setSelectedCodexPreset] = useState<number | null>(
null,
showPresets && isCodex ? -1 : null,
);
// 初始化 Codex 配置
@@ -71,7 +72,10 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
}, [isCodex, initialData]);
const [error, setError] = useState("");
const [disableCoAuthored, setDisableCoAuthored] = useState(false);
const [selectedPreset, setSelectedPreset] = useState<number | null>(null);
// -1 表示自定义null 表示未选择,>= 0 表示预设索引
const [selectedPreset, setSelectedPreset] = useState<number | null>(
showPresets ? -1 : null
);
const [apiKey, setApiKey] = useState("");
// 初始化时检查禁用签名状态
@@ -216,6 +220,18 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
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<ProviderFormProps> = ({
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<ProviderFormProps> = ({
const configString = setApiKeyInConfig(
formData.settingsConfig,
key.trim(),
{ createIfMissing: selectedPreset !== null },
{ createIfMissing: selectedPreset !== null && selectedPreset !== -1 },
);
// 更新表单配置
@@ -271,12 +300,15 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
};
// 根据当前配置决定是否展示 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<ProviderFormProps> = ({
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<ProviderFormProps> = ({
{showPresets && !isCodex && (
<div className="presets">
<label> key</label>
<label></label>
<div className="preset-buttons">
<button
type="button"
className={`preset-btn ${
selectedPreset === -1 ? "selected" : ""
}`}
onClick={handleCustomClick}
>
</button>
{providerPresets.map((preset, index) => {
return (
<button
@@ -364,13 +408,34 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
);
})}
</div>
{selectedPreset === -1 && (
<small className="field-hint" style={{ marginTop: "8px", display: "block" }}>
</small>
)}
{selectedPreset !== -1 && selectedPreset !== null && (
<small className="field-hint" style={{ marginTop: "8px", display: "block" }}>
{isOfficialPreset
? "Claude 官方登录,不需要填写 API Key"
: "使用预设配置,只需填写 API Key"}
</small>
)}
</div>
)}
{showPresets && isCodex && (
<div className="presets">
<label> key</label>
<label></label>
<div className="preset-buttons">
<button
type="button"
className={`preset-btn ${
selectedCodexPreset === -1 ? "selected" : ""
}`}
onClick={handleCodexCustomClick}
>
</button>
{codexProviderPresets.map((preset, index) => (
<button
key={index}
@@ -384,6 +449,18 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
</button>
))}
</div>
{selectedCodexPreset === -1 && (
<small className="field-hint" style={{ marginTop: "8px", display: "block" }}>
</small>
)}
{selectedCodexPreset !== -1 && selectedCodexPreset !== null && (
<small className="field-hint" style={{ marginTop: "8px", display: "block" }}>
{isCodexOfficialPreset
? "Codex 官方登录,不需要填写 API Key"
: "使用预设配置,只需填写 API Key"}
</small>
)}
</div>
)}
@@ -448,7 +525,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
}
disabled={isCodexOfficialPreset}
required={
selectedCodexPreset !== null && !isCodexOfficialPreset
selectedCodexPreset !== null && selectedCodexPreset >= 0 && !isCodexOfficialPreset
}
autoComplete="off"
style={
@@ -521,7 +598,7 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
style={{ fontFamily: "monospace", fontSize: "14px" }}
/>
<small className="field-hint">
Codex config.toml
Codex config.toml
</small>
</div>
</>