mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-03 11:01:22 +08:00
88d5ffba44
updateTomlCommonConfigSnippet re-serialized the whole document through
smol-toml (parse -> deepMerge -> stringify): comments dropped, keys
reordered, and empty parent table headers synthesized -- the
long-standing "config.toml keeps getting reordered" symptom (audit C5,
introduced in 083e48bf).
Replace it with a backend command backed by the same
merge_toml_table_like / remove_toml_table_like used when writing live
configs, so the form preview and the live write share one merge
semantic and user formatting survives edit-time merges. The frontend
sync helper is deleted outright to keep the pattern from coming back.
Making the form operations async exposes them to interleaving, so a
result is discarded unless it is still current when it lands:
- a per-hook sequence number (last operation wins) covers rapid
toggle/save races where an earlier merge resolves after a later
removal and would flip the switch back;
- a config-baseline check covers the user hand-editing the TOML while
a merge is in flight -- the stale result must not clobber their edit.
The checkbox state self-heals via the existing inference effect.
Regression tests pin both by resolving a suspended merge after a newer
operation / an external edit, plus backend tests locking comment and
key-order preservation, scalar override, and value-matched removal.
120 lines
3.0 KiB
TypeScript
120 lines
3.0 KiB
TypeScript
import React, { useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { CodexAuthSection, CodexConfigSection } from "./CodexConfigSections";
|
|
import { CodexCommonConfigModal } from "./CodexCommonConfigModal";
|
|
|
|
interface CodexConfigEditorProps {
|
|
authValue: string;
|
|
|
|
configValue: string;
|
|
|
|
providerName?: string;
|
|
|
|
showRemoteCompaction?: boolean;
|
|
|
|
isProxyTakeover?: boolean;
|
|
|
|
onAuthChange: (value: string) => void;
|
|
|
|
onConfigChange: (value: string) => void;
|
|
|
|
onAuthBlur?: () => void;
|
|
|
|
useCommonConfig: boolean;
|
|
|
|
onCommonConfigToggle: (checked: boolean) => void | Promise<void>;
|
|
|
|
commonConfigSnippet: string;
|
|
|
|
onCommonConfigSnippetChange: (value: string) => boolean | Promise<boolean>;
|
|
|
|
onCommonConfigErrorClear: () => void;
|
|
|
|
commonConfigError: string;
|
|
|
|
authError: string;
|
|
|
|
configError: string; // config.toml 错误提示
|
|
|
|
onExtract?: () => void;
|
|
|
|
isExtracting?: boolean;
|
|
}
|
|
|
|
const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
|
|
authValue,
|
|
configValue,
|
|
providerName,
|
|
showRemoteCompaction,
|
|
isProxyTakeover = false,
|
|
onAuthChange,
|
|
onConfigChange,
|
|
onAuthBlur,
|
|
useCommonConfig,
|
|
onCommonConfigToggle,
|
|
commonConfigSnippet,
|
|
onCommonConfigSnippetChange,
|
|
onCommonConfigErrorClear,
|
|
commonConfigError,
|
|
authError,
|
|
configError,
|
|
onExtract,
|
|
isExtracting,
|
|
}) => {
|
|
const { t } = useTranslation();
|
|
const [isCommonConfigModalOpen, setIsCommonConfigModalOpen] = useState(false);
|
|
|
|
const handleCloseCommonConfigModal = () => {
|
|
onCommonConfigErrorClear();
|
|
setIsCommonConfigModalOpen(false);
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{isProxyTakeover && (
|
|
<div className="p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-700 rounded-lg">
|
|
<p className="text-xs text-amber-600 dark:text-amber-400">
|
|
{t("codexConfig.proxyTakeoverStorageNotice")}
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
{/* Auth JSON Section */}
|
|
<CodexAuthSection
|
|
value={authValue}
|
|
onChange={onAuthChange}
|
|
onBlur={onAuthBlur}
|
|
error={authError}
|
|
isProxyTakeover={isProxyTakeover}
|
|
/>
|
|
|
|
{/* Config TOML Section */}
|
|
<CodexConfigSection
|
|
value={configValue}
|
|
onChange={onConfigChange}
|
|
providerName={providerName}
|
|
showRemoteCompaction={showRemoteCompaction}
|
|
useCommonConfig={useCommonConfig}
|
|
onCommonConfigToggle={onCommonConfigToggle}
|
|
onEditCommonConfig={() => setIsCommonConfigModalOpen(true)}
|
|
commonConfigError={commonConfigError}
|
|
configError={configError}
|
|
isProxyTakeover={isProxyTakeover}
|
|
/>
|
|
|
|
{/* Common Config Modal */}
|
|
<CodexCommonConfigModal
|
|
isOpen={isCommonConfigModalOpen}
|
|
onClose={handleCloseCommonConfigModal}
|
|
value={commonConfigSnippet}
|
|
onSave={onCommonConfigSnippetChange}
|
|
error={commonConfigError}
|
|
onExtract={onExtract}
|
|
isExtracting={isExtracting}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CodexConfigEditor;
|