refactor(app): replace providers-snapshot invalidate with refetchIfStale

invalidate() flagged the query stale and kicked off a refetch unconditionally,
causing a loading flash every time the model selector opened. Expose
refetchIfStale() instead so callers only refetch when data is actually stale.
This commit is contained in:
Mohamed Boudra
2026-04-18 16:03:13 +07:00
parent 5d76cc8840
commit 72e4476acc
4 changed files with 17 additions and 19 deletions
@@ -867,8 +867,7 @@ export const AgentStatusBar = memo(function AgentStatusBar({
const { const {
entries: snapshotEntries, entries: snapshotEntries,
isLoading: snapshotIsLoading, isLoading: snapshotIsLoading,
isFetching: snapshotIsFetching, refetchIfStale: refetchSnapshotIfStale,
invalidate: invalidateSnapshot,
} = useProvidersSnapshot(serverId, agent?.cwd); } = useProvidersSnapshot(serverId, agent?.cwd);
const snapshotModels = useMemo(() => { const snapshotModels = useMemo(() => {
@@ -1034,8 +1033,8 @@ export const AgentStatusBar = memo(function AgentStatusBar({
console.warn("[AgentStatusBar] setAgentFeature failed", error); console.warn("[AgentStatusBar] setAgentFeature failed", error);
}); });
}} }}
isModelLoading={snapshotIsLoading || snapshotIsFetching} isModelLoading={snapshotIsLoading}
onModelSelectorOpen={invalidateSnapshot} onModelSelectorOpen={refetchSnapshotIfStale}
onDropdownClose={onDropdownClose} onDropdownClose={onDropdownClose}
disabled={!client} disabled={!client}
/> />
+9 -10
View File
@@ -91,7 +91,7 @@ export type UseAgentFormStateResult = {
isModelLoading: boolean; isModelLoading: boolean;
modelError: string | null; modelError: string | null;
refreshProviderModels: () => void; refreshProviderModels: () => void;
invalidateProviderModels: () => void; refetchProviderModelsIfStale: () => void;
setProviderAndModelFromUser: (provider: AgentProvider, modelId: string) => void; setProviderAndModelFromUser: (provider: AgentProvider, modelId: string) => void;
workingDirIsEmpty: boolean; workingDirIsEmpty: boolean;
persistFormPreferences: () => Promise<void>; persistFormPreferences: () => Promise<void>;
@@ -360,10 +360,9 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
const { const {
entries: snapshotEntries, entries: snapshotEntries,
isLoading: snapshotIsLoading, isLoading: snapshotIsLoading,
isFetching: snapshotIsFetching,
error: snapshotError, error: snapshotError,
refresh: refreshSnapshot, refresh: refreshSnapshot,
invalidate: invalidateSnapshot, refetchIfStale: refetchSnapshotIfStale,
} = useProvidersSnapshot(formState.serverId, formState.workingDir); } = useProvidersSnapshot(formState.serverId, formState.workingDir);
const allProviderEntries = useMemo(() => snapshotEntries ?? [], [snapshotEntries]); const allProviderEntries = useMemo(() => snapshotEntries ?? [], [snapshotEntries]);
@@ -413,7 +412,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
const allProviderModels = snapshotAllProviderModels; const allProviderModels = snapshotAllProviderModels;
const availableModels = snapshotSelectedProviderModels; const availableModels = snapshotSelectedProviderModels;
const modeOptions = snapshotSelectedProviderModes; const modeOptions = snapshotSelectedProviderModes;
const isAllModelsLoading = snapshotIsLoading || snapshotIsFetching; const isAllModelsLoading = snapshotIsLoading;
// Combine initialValues with initialServerId for resolution // Combine initialValues with initialServerId for resolution
const combinedInitialValues = useMemo((): FormInitialValues | undefined => { const combinedInitialValues = useMemo((): FormInitialValues | undefined => {
@@ -625,9 +624,9 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
refreshSnapshot(); refreshSnapshot();
}, [refreshSnapshot]); }, [refreshSnapshot]);
const invalidateProviderModels = useCallback(() => { const refetchProviderModelsIfStale = useCallback(() => {
invalidateSnapshot(); refetchSnapshotIfStale();
}, [invalidateSnapshot]); }, [refetchSnapshotIfStale]);
const persistFormPreferences = useCallback(async () => { const persistFormPreferences = useCallback(async () => {
const resolvedModel = resolveEffectiveModel(availableModels, formState.model); const resolvedModel = resolveEffectiveModel(availableModels, formState.model);
@@ -662,7 +661,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
const effectiveModel = resolveEffectiveModel(availableModels, formState.model); const effectiveModel = resolveEffectiveModel(availableModels, formState.model);
const resolvedModelId = effectiveModel?.id ?? formState.model; const resolvedModelId = effectiveModel?.id ?? formState.model;
const availableThinkingOptions = effectiveModel?.thinkingOptions ?? []; const availableThinkingOptions = effectiveModel?.thinkingOptions ?? [];
const isModelLoading = snapshotIsLoading || snapshotIsFetching; const isModelLoading = snapshotIsLoading;
const modelError = snapshotError; const modelError = snapshotError;
const workingDirIsEmpty = !formState.workingDir.trim(); const workingDirIsEmpty = !formState.workingDir.trim();
@@ -695,7 +694,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
isModelLoading, isModelLoading,
modelError, modelError,
refreshProviderModels, refreshProviderModels,
invalidateProviderModels, refetchProviderModelsIfStale,
setProviderAndModelFromUser, setProviderAndModelFromUser,
workingDirIsEmpty, workingDirIsEmpty,
persistFormPreferences, persistFormPreferences,
@@ -727,7 +726,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
isModelLoading, isModelLoading,
modelError, modelError,
refreshProviderModels, refreshProviderModels,
invalidateProviderModels, refetchProviderModelsIfStale,
setProviderAndModelFromUser, setProviderAndModelFromUser,
workingDirIsEmpty, workingDirIsEmpty,
persistFormPreferences, persistFormPreferences,
@@ -167,7 +167,7 @@ function buildDraftStatusControls(input: {
features, features,
onSetFeature, onSetFeature,
onDropdownClose, onDropdownClose,
onModelSelectorOpen: formState.invalidateProviderModels, onModelSelectorOpen: formState.refetchProviderModelsIfStale,
}; };
} }
@@ -27,7 +27,7 @@ interface UseProvidersSnapshotResult {
error: string | null; error: string | null;
supportsSnapshot: boolean; supportsSnapshot: boolean;
refresh: (providers?: AgentProvider[]) => Promise<void>; refresh: (providers?: AgentProvider[]) => Promise<void>;
invalidate: () => void; refetchIfStale: () => void;
} }
export function useProvidersSnapshot( export function useProvidersSnapshot(
@@ -99,8 +99,8 @@ export function useProvidersSnapshot(
[refreshSnapshot], [refreshSnapshot],
); );
const invalidate = useCallback(() => { const refetchIfStale = useCallback(() => {
void queryClient.invalidateQueries({ queryKey }); void queryClient.refetchQueries({ queryKey, type: "active", stale: true });
}, [queryClient, queryKey]); }, [queryClient, queryKey]);
return { return {
@@ -111,7 +111,7 @@ export function useProvidersSnapshot(
error: snapshotQuery.error instanceof Error ? snapshotQuery.error.message : null, error: snapshotQuery.error instanceof Error ? snapshotQuery.error.message : null,
supportsSnapshot, supportsSnapshot,
refresh, refresh,
invalidate, refetchIfStale,
}; };
} }