Files
cc-switch/src/components/providers/EditProviderDialog.tsx
YoVinchen e8d4397b3a refactor(ui): unify dialog styles and improve layout consistency
Standardize dialog and panel components across the application.
- Update dialog background to use semantic color tokens
- Adjust FullScreenPanel max-width to 56rem for better alignment
- Add drag region and prevent body scroll in full-screen panels
- Optimize button sizes and spacing in panel headers
- Apply consistent styling to all dialog-based components
2025-11-22 14:03:09 +08:00

147 lines
4.1 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 { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { Save } from "lucide-react";
import { Button } from "@/components/ui/button";
import { FullScreenPanel } from "@/components/common/FullScreenPanel";
import type { Provider } from "@/types";
import {
ProviderForm,
type ProviderFormValues,
} from "@/components/providers/forms/ProviderForm";
import { providersApi, vscodeApi, type AppId } from "@/lib/api";
interface EditProviderDialogProps {
open: boolean;
provider: Provider | null;
onOpenChange: (open: boolean) => void;
onSubmit: (provider: Provider) => Promise<void> | void;
appId: AppId;
}
export function EditProviderDialog({
open,
provider,
onOpenChange,
onSubmit,
appId,
}: EditProviderDialogProps) {
const { t } = useTranslation();
// 默认使用传入的 provider.settingsConfig若当前编辑对象是"当前生效供应商",则尝试读取实时配置替换初始值
const [liveSettings, setLiveSettings] = useState<Record<
string,
unknown
> | null>(null);
useEffect(() => {
let cancelled = false;
const load = async () => {
if (!open || !provider) {
setLiveSettings(null);
return;
}
try {
const currentId = await providersApi.getCurrent(appId);
if (currentId && provider.id === currentId) {
try {
const live = (await vscodeApi.getLiveProviderSettings(
appId,
)) as Record<string, unknown>;
if (!cancelled && live && typeof live === "object") {
setLiveSettings(live);
}
} catch {
// 读取实时配置失败则回退到 SSOT不打断编辑流程
if (!cancelled) setLiveSettings(null);
}
} else {
if (!cancelled) setLiveSettings(null);
}
} finally {
// no-op
}
};
void load();
return () => {
cancelled = true;
};
}, [open, provider, appId]);
const initialSettingsConfig = useMemo(() => {
return (liveSettings ?? provider?.settingsConfig ?? {}) as Record<
string,
unknown
>;
}, [liveSettings, provider]);
const handleSubmit = useCallback(
async (values: ProviderFormValues) => {
if (!provider) return;
const parsedConfig = JSON.parse(values.settingsConfig) as Record<
string,
unknown
>;
const updatedProvider: Provider = {
...provider,
name: values.name.trim(),
notes: values.notes?.trim() || undefined,
websiteUrl: values.websiteUrl?.trim() || undefined,
settingsConfig: parsedConfig,
icon: values.icon?.trim() || undefined,
iconColor: values.iconColor?.trim() || undefined,
...(values.presetCategory ? { category: values.presetCategory } : {}),
// 保留或更新 meta 字段
...(values.meta ? { meta: values.meta } : {}),
};
await onSubmit(updatedProvider);
onOpenChange(false);
},
[onSubmit, onOpenChange, provider],
);
if (!provider) {
return null;
}
return (
<FullScreenPanel
isOpen={open}
title={t("provider.editProvider")}
onClose={() => onOpenChange(false)}
footer={
<Button
type="submit"
form="provider-form"
className="bg-primary text-primary-foreground hover:bg-primary/90"
>
<Save className="h-4 w-4 mr-2" />
{t("common.save")}
</Button>
}
>
<ProviderForm
appId={appId}
providerId={provider.id}
submitLabel={t("common.save")}
onSubmit={handleSubmit}
onCancel={() => onOpenChange(false)}
initialData={{
name: provider.name,
notes: provider.notes,
websiteUrl: provider.websiteUrl,
// 若读取到实时配置则优先使用
settingsConfig: initialSettingsConfig,
category: provider.category,
meta: provider.meta,
icon: provider.icon,
iconColor: provider.iconColor,
}}
showButtons={false}
/>
</FullScreenPanel>
);
}