Files
cc-switch/src/components/providers/forms/CodexFormFields.tsx

104 lines
2.8 KiB
TypeScript
Raw Normal View History

import { useTranslation } from "react-i18next";
import EndpointSpeedTest from "./EndpointSpeedTest";
import { ApiKeySection, EndpointField } from "./shared";
import type { ProviderCategory } from "@/types";
interface EndpointCandidate {
url: string;
}
interface CodexFormFieldsProps {
refactor(endpoints): implement deferred submission and fix clear-all bug Implement Solution A (complete deferred submission) for custom endpoint management, replacing the dual-mode system with unified local staging. Changes: - Remove immediate backend saves from EndpointSpeedTest * handleAddEndpoint: local state update only * handleRemoveEndpoint: local state update only * handleSelect: remove lastUsed timestamp update - Add explicit clear detection in ProviderForm * Distinguish "user cleared endpoints" from "user didn't modify" * Pass empty object {} as clear signal vs null for no-change - Fix mergeProviderMeta to handle three distinct cases: * null/undefined: don't modify endpoints (no meta sent) * empty object {}: explicitly clear endpoints (send empty meta) * with data: add/update endpoints (overwrite) Fixed Critical Bug: When users deleted all custom endpoints, changes were not saved because: - draftCustomEndpoints=[] resulted in customEndpointsToSave=null - mergeProviderMeta(meta, null) returned undefined - Backend interpreted missing meta as "don't modify", preserving old values Solution: Detect when user had endpoints and cleared them (hadEndpoints && length===0), then pass empty object to mergeProviderMeta as explicit clear signal. Architecture Improvements: - Transaction atomicity: all fields submitted together on form save - UX consistency: add/edit modes behave identically - Cancel button: true rollback with no immediate saves - Code simplification: removed ~40 lines of immediate save error handling Testing: - TypeScript type check: passed - Rust backend tests: 10/10 passed - Build: successful
2025-11-04 15:30:54 +08:00
providerId?: string;
// API Key
codexApiKey: string;
onApiKeyChange: (key: string) => void;
category?: ProviderCategory;
shouldShowApiKeyLink: boolean;
websiteUrl: string;
isPartner?: boolean;
partnerPromotionKey?: string;
// Base URL
shouldShowSpeedTest: boolean;
codexBaseUrl: string;
onBaseUrlChange: (url: string) => void;
isEndpointModalOpen: boolean;
onEndpointModalToggle: (open: boolean) => void;
onCustomEndpointsChange?: (endpoints: string[]) => void;
// Speed Test Endpoints
speedTestEndpoints: EndpointCandidate[];
}
export function CodexFormFields({
refactor(endpoints): implement deferred submission and fix clear-all bug Implement Solution A (complete deferred submission) for custom endpoint management, replacing the dual-mode system with unified local staging. Changes: - Remove immediate backend saves from EndpointSpeedTest * handleAddEndpoint: local state update only * handleRemoveEndpoint: local state update only * handleSelect: remove lastUsed timestamp update - Add explicit clear detection in ProviderForm * Distinguish "user cleared endpoints" from "user didn't modify" * Pass empty object {} as clear signal vs null for no-change - Fix mergeProviderMeta to handle three distinct cases: * null/undefined: don't modify endpoints (no meta sent) * empty object {}: explicitly clear endpoints (send empty meta) * with data: add/update endpoints (overwrite) Fixed Critical Bug: When users deleted all custom endpoints, changes were not saved because: - draftCustomEndpoints=[] resulted in customEndpointsToSave=null - mergeProviderMeta(meta, null) returned undefined - Backend interpreted missing meta as "don't modify", preserving old values Solution: Detect when user had endpoints and cleared them (hadEndpoints && length===0), then pass empty object to mergeProviderMeta as explicit clear signal. Architecture Improvements: - Transaction atomicity: all fields submitted together on form save - UX consistency: add/edit modes behave identically - Cancel button: true rollback with no immediate saves - Code simplification: removed ~40 lines of immediate save error handling Testing: - TypeScript type check: passed - Rust backend tests: 10/10 passed - Build: successful
2025-11-04 15:30:54 +08:00
providerId,
codexApiKey,
onApiKeyChange,
category,
shouldShowApiKeyLink,
websiteUrl,
isPartner,
partnerPromotionKey,
shouldShowSpeedTest,
codexBaseUrl,
onBaseUrlChange,
isEndpointModalOpen,
onEndpointModalToggle,
onCustomEndpointsChange,
speedTestEndpoints,
}: CodexFormFieldsProps) {
const { t } = useTranslation();
return (
<>
{/* Codex API Key 输入框 */}
<ApiKeySection
id="codexApiKey"
label="API Key"
value={codexApiKey}
onChange={onApiKeyChange}
category={category}
shouldShowLink={shouldShowApiKeyLink}
websiteUrl={websiteUrl}
isPartner={isPartner}
partnerPromotionKey={partnerPromotionKey}
placeholder={{
official: t("providerForm.codexOfficialNoApiKey", {
defaultValue: "官方供应商无需 API Key",
}),
thirdParty: t("providerForm.codexApiKeyAutoFill", {
defaultValue: "输入 API Key将自动填充到配置",
}),
}}
/>
{/* Codex Base URL 输入框 */}
{shouldShowSpeedTest && (
<EndpointField
id="codexBaseUrl"
label={t("codexConfig.apiUrlLabel")}
value={codexBaseUrl}
onChange={onBaseUrlChange}
placeholder={t("providerForm.codexApiEndpointPlaceholder")}
hint={t("providerForm.codexApiHint")}
onManageClick={() => onEndpointModalToggle(true)}
/>
)}
{/* 端点测速弹窗 - Codex */}
{shouldShowSpeedTest && isEndpointModalOpen && (
<EndpointSpeedTest
appId="codex"
refactor(endpoints): implement deferred submission and fix clear-all bug Implement Solution A (complete deferred submission) for custom endpoint management, replacing the dual-mode system with unified local staging. Changes: - Remove immediate backend saves from EndpointSpeedTest * handleAddEndpoint: local state update only * handleRemoveEndpoint: local state update only * handleSelect: remove lastUsed timestamp update - Add explicit clear detection in ProviderForm * Distinguish "user cleared endpoints" from "user didn't modify" * Pass empty object {} as clear signal vs null for no-change - Fix mergeProviderMeta to handle three distinct cases: * null/undefined: don't modify endpoints (no meta sent) * empty object {}: explicitly clear endpoints (send empty meta) * with data: add/update endpoints (overwrite) Fixed Critical Bug: When users deleted all custom endpoints, changes were not saved because: - draftCustomEndpoints=[] resulted in customEndpointsToSave=null - mergeProviderMeta(meta, null) returned undefined - Backend interpreted missing meta as "don't modify", preserving old values Solution: Detect when user had endpoints and cleared them (hadEndpoints && length===0), then pass empty object to mergeProviderMeta as explicit clear signal. Architecture Improvements: - Transaction atomicity: all fields submitted together on form save - UX consistency: add/edit modes behave identically - Cancel button: true rollback with no immediate saves - Code simplification: removed ~40 lines of immediate save error handling Testing: - TypeScript type check: passed - Rust backend tests: 10/10 passed - Build: successful
2025-11-04 15:30:54 +08:00
providerId={providerId}
value={codexBaseUrl}
onChange={onBaseUrlChange}
initialEndpoints={speedTestEndpoints}
visible={isEndpointModalOpen}
onClose={() => onEndpointModalToggle(false)}
onCustomEndpointsChange={onCustomEndpointsChange}
/>
)}
</>
);
}