refactor: create modular hooks and integrate API key input
- Create custom hooks for state management: - useProviderCategory: manages provider category state - useApiKeyState: manages API key input with auto-sync to config - useBaseUrlState: manages base URL for Claude and Codex - useModelState: manages model selection state - Integrate API key input into simplified ProviderForm: - Add ApiKeyInput component for Claude mode - Auto-populate API key into settings config - Disable for official providers - Fix EndpointSpeedTest type errors: - Fix import paths to use @ alias - Add temporary type definitions - Format all TODO comments properly - Remove incorrect type assertions - Comment out unimplemented window.api checks All TypeScript type checks now pass.
This commit is contained in:
114
src/components/providers/forms/hooks/useBaseUrlState.ts
Normal file
114
src/components/providers/forms/hooks/useBaseUrlState.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { useState, useCallback, useRef, useEffect } from "react";
|
||||
import { extractCodexBaseUrl, setCodexBaseUrl as setCodexBaseUrlInConfig } from "@/utils/providerConfigUtils";
|
||||
import type { ProviderCategory } from "@/types";
|
||||
|
||||
interface UseBaseUrlStateProps {
|
||||
appType: "claude" | "codex";
|
||||
category: ProviderCategory | undefined;
|
||||
settingsConfig: string;
|
||||
codexConfig?: string;
|
||||
onSettingsConfigChange: (config: string) => void;
|
||||
onCodexConfigChange?: (config: string) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理 Base URL 状态
|
||||
* 支持 Claude (JSON) 和 Codex (TOML) 两种格式
|
||||
*/
|
||||
export function useBaseUrlState({
|
||||
appType,
|
||||
category,
|
||||
settingsConfig,
|
||||
codexConfig,
|
||||
onSettingsConfigChange,
|
||||
onCodexConfigChange,
|
||||
}: UseBaseUrlStateProps) {
|
||||
const [baseUrl, setBaseUrl] = useState("");
|
||||
const [codexBaseUrl, setCodexBaseUrl] = useState("");
|
||||
const isUpdatingRef = useRef(false);
|
||||
|
||||
// 从配置同步到 state(Claude)
|
||||
useEffect(() => {
|
||||
if (appType !== "claude") return;
|
||||
if (category !== "third_party" && category !== "custom") return;
|
||||
if (isUpdatingRef.current) return;
|
||||
|
||||
try {
|
||||
const config = JSON.parse(settingsConfig || "{}");
|
||||
const envUrl: unknown = config?.env?.ANTHROPIC_BASE_URL;
|
||||
if (typeof envUrl === "string" && envUrl && envUrl !== baseUrl) {
|
||||
setBaseUrl(envUrl.trim());
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}, [appType, category, settingsConfig, baseUrl]);
|
||||
|
||||
// 从配置同步到 state(Codex)
|
||||
useEffect(() => {
|
||||
if (appType !== "codex") return;
|
||||
if (category !== "third_party" && category !== "custom") return;
|
||||
if (isUpdatingRef.current) return;
|
||||
if (!codexConfig) return;
|
||||
|
||||
const extracted = extractCodexBaseUrl(codexConfig) || "";
|
||||
if (extracted !== codexBaseUrl) {
|
||||
setCodexBaseUrl(extracted);
|
||||
}
|
||||
}, [appType, category, codexConfig, codexBaseUrl]);
|
||||
|
||||
// 处理 Claude Base URL 变化
|
||||
const handleClaudeBaseUrlChange = useCallback(
|
||||
(url: string) => {
|
||||
const sanitized = url.trim().replace(/\/+$/, "");
|
||||
setBaseUrl(sanitized);
|
||||
isUpdatingRef.current = true;
|
||||
|
||||
try {
|
||||
const config = JSON.parse(settingsConfig || "{}");
|
||||
if (!config.env) {
|
||||
config.env = {};
|
||||
}
|
||||
config.env.ANTHROPIC_BASE_URL = sanitized;
|
||||
onSettingsConfigChange(JSON.stringify(config, null, 2));
|
||||
} catch {
|
||||
// ignore
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
isUpdatingRef.current = false;
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
[settingsConfig, onSettingsConfigChange],
|
||||
);
|
||||
|
||||
// 处理 Codex Base URL 变化
|
||||
const handleCodexBaseUrlChange = useCallback(
|
||||
(url: string) => {
|
||||
const sanitized = url.trim().replace(/\/+$/, "");
|
||||
setCodexBaseUrl(sanitized);
|
||||
|
||||
if (!sanitized || !onCodexConfigChange) {
|
||||
return;
|
||||
}
|
||||
|
||||
isUpdatingRef.current = true;
|
||||
const updatedConfig = setCodexBaseUrlInConfig(codexConfig || "", sanitized);
|
||||
onCodexConfigChange(updatedConfig);
|
||||
|
||||
setTimeout(() => {
|
||||
isUpdatingRef.current = false;
|
||||
}, 0);
|
||||
},
|
||||
[codexConfig, onCodexConfigChange],
|
||||
);
|
||||
|
||||
return {
|
||||
baseUrl,
|
||||
setBaseUrl,
|
||||
codexBaseUrl,
|
||||
setCodexBaseUrl,
|
||||
handleClaudeBaseUrlChange,
|
||||
handleCodexBaseUrlChange,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user