Files
CC-Switch/src/components/providers/forms/hooks/useCodexConfigState.ts
T
Jason 57552b3159 fix: unify dialog layout and fix content padding issues
- Fix negative margin overflow in all dialog content areas
- Standardize dialog structure with flex-col layout
- Add consistent py-4 spacing to all content areas
- Ensure proper spacing between header, content, and footer

Affected components:
- AddProviderDialog, EditProviderDialog
- McpFormModal, McpPanel
- UsageScriptModal
- SettingsDialog

All dialogs now follow unified layout pattern:
- DialogContent: flex flex-col max-h-[90vh]
- Content area: flex-1 overflow-y-auto px-6 py-4
- No negative margins that cause content overflow
2025-10-18 16:52:02 +08:00

207 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState, useCallback, useEffect, useRef } from "react";
import {
extractCodexBaseUrl,
setCodexBaseUrl as setCodexBaseUrlInConfig,
} from "@/utils/providerConfigUtils";
interface UseCodexConfigStateProps {
initialData?: {
settingsConfig?: Record<string, unknown>;
};
}
/**
* 管理 Codex 配置状态
* Codex 配置包含两部分:auth.json (JSON) 和 config.toml (TOML 字符串)
*/
export function useCodexConfigState({ initialData }: UseCodexConfigStateProps) {
const [codexAuth, setCodexAuthState] = useState("");
const [codexConfig, setCodexConfigState] = useState("");
const [codexApiKey, setCodexApiKey] = useState("");
const [codexBaseUrl, setCodexBaseUrl] = useState("");
const [codexAuthError, setCodexAuthError] = useState("");
const isUpdatingCodexBaseUrlRef = useRef(false);
// 初始化 Codex 配置(编辑模式)
useEffect(() => {
if (!initialData) return;
const config = initialData.settingsConfig;
if (typeof config === "object" && config !== null) {
// 设置 auth.json
const auth = (config as any).auth || {};
setCodexAuthState(JSON.stringify(auth, null, 2));
// 设置 config.toml
const configStr =
typeof (config as any).config === "string"
? (config as any).config
: "";
setCodexConfigState(configStr);
// 提取 Base URL
const initialBaseUrl = extractCodexBaseUrl(configStr);
if (initialBaseUrl) {
setCodexBaseUrl(initialBaseUrl);
}
// 提取 API Key
try {
if (auth && typeof auth.OPENAI_API_KEY === "string") {
setCodexApiKey(auth.OPENAI_API_KEY);
}
} catch {
// ignore
}
}
}, [initialData]);
// 与 TOML 配置保持基础 URL 同步
useEffect(() => {
if (isUpdatingCodexBaseUrlRef.current) {
return;
}
const extracted = extractCodexBaseUrl(codexConfig) || "";
if (extracted !== codexBaseUrl) {
setCodexBaseUrl(extracted);
}
}, [codexConfig, codexBaseUrl]);
// 验证 Codex Auth JSON
const validateCodexAuth = useCallback((value: string): string => {
if (!value.trim()) return "";
try {
const parsed = JSON.parse(value);
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
return "Auth JSON must be an object";
}
return "";
} catch {
return "Invalid JSON format";
}
}, []);
// 设置 auth 并验证
const setCodexAuth = useCallback(
(value: string) => {
setCodexAuthState(value);
setCodexAuthError(validateCodexAuth(value));
},
[validateCodexAuth],
);
// 设置 config (支持函数更新)
const setCodexConfig = useCallback(
(value: string | ((prev: string) => string)) => {
setCodexConfigState((prev) =>
typeof value === "function"
? (value as (input: string) => string)(prev)
: value,
);
},
[],
);
// 处理 Codex API Key 输入并写回 auth.json
const handleCodexApiKeyChange = useCallback(
(key: string) => {
setCodexApiKey(key);
try {
const auth = JSON.parse(codexAuth || "{}");
auth.OPENAI_API_KEY = key.trim();
setCodexAuth(JSON.stringify(auth, null, 2));
} catch {
// ignore
}
},
[codexAuth, setCodexAuth],
);
// 处理 Codex Base URL 变化
const handleCodexBaseUrlChange = useCallback(
(url: string) => {
const sanitized = url.trim().replace(/\/+$/, "");
setCodexBaseUrl(sanitized);
if (!sanitized) {
return;
}
isUpdatingCodexBaseUrlRef.current = true;
setCodexConfig((prev) => setCodexBaseUrlInConfig(prev, sanitized));
setTimeout(() => {
isUpdatingCodexBaseUrlRef.current = false;
}, 0);
},
[setCodexConfig],
);
// 处理 config 变化(同步 Base URL
const handleCodexConfigChange = useCallback(
(value: string) => {
setCodexConfig(value);
if (!isUpdatingCodexBaseUrlRef.current) {
const extracted = extractCodexBaseUrl(value) || "";
if (extracted !== codexBaseUrl) {
setCodexBaseUrl(extracted);
}
}
},
[setCodexConfig, codexBaseUrl],
);
// 重置配置(用于预设切换)
const resetCodexConfig = useCallback(
(auth: Record<string, unknown>, config: string) => {
const authString = JSON.stringify(auth, null, 2);
setCodexAuth(authString);
setCodexConfig(config);
const baseUrl = extractCodexBaseUrl(config);
if (baseUrl) {
setCodexBaseUrl(baseUrl);
}
// 提取 API Key
try {
if (auth && typeof auth.OPENAI_API_KEY === "string") {
setCodexApiKey(auth.OPENAI_API_KEY);
} else {
setCodexApiKey("");
}
} catch {
setCodexApiKey("");
}
},
[setCodexAuth, setCodexConfig],
);
// 获取 API Key(从 auth JSON
const getCodexAuthApiKey = useCallback((authString: string): string => {
try {
const auth = JSON.parse(authString || "{}");
return typeof auth.OPENAI_API_KEY === "string" ? auth.OPENAI_API_KEY : "";
} catch {
return "";
}
}, []);
return {
codexAuth,
codexConfig,
codexApiKey,
codexBaseUrl,
codexAuthError,
setCodexAuth,
setCodexConfig,
handleCodexApiKeyChange,
handleCodexBaseUrlChange,
handleCodexConfigChange,
resetCodexConfig,
getCodexAuthApiKey,
validateCodexAuth,
};
}