fix(setting-model): keep newly saved instance card expanded after name save (#16904)

This commit is contained in:
chanx
2026-07-14 20:11:45 +08:00
committed by GitHub
parent 3087eb854c
commit 376a9057a8
5 changed files with 27 additions and 12 deletions

View File

@@ -56,6 +56,10 @@ const SettingModelV2: FC = () => {
// cancelled independently; saving removes the draft from this list and
// triggers a refetch that surfaces the newly-saved instance above.
const [draftIds, setDraftIds] = useState<string[]>([]);
const [newlySavedInstanceName, setNewlySavedInstanceName] = useState<
string | null
>(null);
// Monotonic counter so each draft card has a stable, unique React key.
const draftIdCounterRef = useRef(0);
// Tracks whether the user explicitly cancelled the auto-shown draft
@@ -90,6 +94,7 @@ const SettingModelV2: FC = () => {
useEffect(() => {
cancelledRef.current = false;
setDraftIds([]);
setNewlySavedInstanceName(null);
}, [selection]);
// If the user switches to a provider with no existing instances and
@@ -135,6 +140,7 @@ const SettingModelV2: FC = () => {
// and `draftIds` are empty and would otherwise re-trigger
// `addDraft()`).
cancelledRef.current = true;
setNewlySavedInstanceName(values.instance_name);
removeDraft(id);
queryClient.invalidateQueries({
queryKey: LlmKeys.providerInstances(providerQueryName),
@@ -154,10 +160,12 @@ const SettingModelV2: FC = () => {
// "Save name" button inside the draft card). Remove the draft and
// pin the auto-show guard so a new placeholder draft is not
// auto-injected during the brief window between draft removal and
// the providerInstances refetch landing.
// the providerInstances refetch landing. Remember the saved name so
// the persisted card mounts expanded.
const handleNameSaved = useCallback(
(id: string) => {
(id: string, instanceName: string) => {
cancelledRef.current = true;
setNewlySavedInstanceName(instanceName);
removeDraft(id);
},
[removeDraft],
@@ -207,7 +215,10 @@ const SettingModelV2: FC = () => {
key={instance.instance_name}
providerName={selection as string}
instance={instance}
defaultOpen={index === 0}
defaultOpen={
index === 0 ||
instance.instance_name === newlySavedInstanceName
}
/>
))}
{draftIds.map((id) => (
@@ -217,7 +228,9 @@ const SettingModelV2: FC = () => {
instance={draftInstance}
isDraft
onDelete={() => handleDraftCancel(id)}
onNameSaved={() => handleNameSaved(id)}
onNameSaved={(instanceName) =>
handleNameSaved(id, instanceName)
}
onSaved={(values) => handleDraftSave(id, values)}
/>
))}

View File

@@ -77,7 +77,7 @@ interface BedrockInstanceCardProps {
instance: IProviderInstance;
isDraft?: boolean;
onSaved?: (values: Record<string, any>) => void | Promise<void>;
onNameSaved?: () => void;
onNameSaved?: (instanceName: string) => void;
onDelete?: () => void;
/**
* When true, this card starts expanded and fetches its instance
@@ -324,7 +324,7 @@ export function BedrockInstanceCard({
instance_name: trimmed,
} as any);
if (ret?.code === 0) {
onNameSaved?.();
onNameSaved?.(trimmed);
}
}, [draftName, addProviderInstance, providerName, onNameSaved]);

View File

@@ -336,7 +336,7 @@ export function useVerifyProvider(
export function useSaveInstanceName(
providerName: string,
draftName: string,
onNameSaved?: () => void,
onNameSaved?: (instanceName: string) => void,
) {
const { addProviderInstance } = useAddProviderInstance();
return useCallback(async () => {
@@ -347,7 +347,7 @@ export function useSaveInstanceName(
instance_name: trimmed,
} as any);
if (ret?.code === 0) {
onNameSaved?.();
onNameSaved?.(trimmed);
}
}, [draftName, addProviderInstance, providerName, onNameSaved]);
}

View File

@@ -39,9 +39,11 @@ export interface ProviderInstanceCardProps {
* Called after a draft instance's *name* has been persisted via
* `addProviderInstance` (with just `instance_name`). The parent should
* remove this draft from its visible list; the freshly invalidated
* `providerInstances` query will surface the persisted card.
* `providerInstances` query will surface the persisted card. The
* saved `instanceName` is passed so the parent can keep the newly
* persisted card expanded.
*/
onNameSaved?: () => void;
onNameSaved?: (instanceName: string) => void;
/**
* Called when the user deletes a draft instance.
* For drafts this is equivalent to onCancel; for saved instances

View File

@@ -104,7 +104,7 @@ interface SoMarkInstanceCardProps {
instance: IProviderInstance;
isDraft?: boolean;
onSaved?: (values: Record<string, any>) => void | Promise<void>;
onNameSaved?: () => void;
onNameSaved?: (instanceName: string) => void;
onDelete?: () => void;
/**
* When true, this card starts expanded and fetches its instance
@@ -355,7 +355,7 @@ export function SoMarkInstanceCard({
instance_name: trimmed,
} as any);
if (ret?.code === 0) {
onNameSaved?.();
onNameSaved?.(trimmed);
}
}, [draftName, addProviderInstance, providerName, onNameSaved]);