Files
CC-Switch/src/components/providers/forms/hooks/useBaseUrlState.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

121 lines
3.2 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, 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);
// 从配置同步到 stateClaude
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]);
// 从配置同步到 stateCodex
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,
};
}