From 436f0e8e4225ff9d0d587d0b1d389beb805da8be Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 19 Nov 2025 09:28:53 +0800 Subject: [PATCH] fix: sync Gemini form fields with env editor The Gemini API key, base URL, and model inputs were not syncing with the env editor below due to data source mismatch. The form was using generic hooks (useApiKeyState, useBaseUrlState) that only updated settingsConfig, while the env editor relied on geminiEnv from useGeminiConfigState. Changes: - Use geminiApiKey/geminiBaseUrl from useGeminiConfigState instead of generic hooks - Wrap handlers to maintain bidirectional sync between geminiEnv and settingsConfig - Remove unused handleGeminiBaseUrlChange from useBaseUrlState to avoid naming conflicts Now all Gemini form fields properly sync with the env editor in both directions. --- .../providers/forms/ProviderForm.tsx | 65 ++++++++++++++----- 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/src/components/providers/forms/ProviderForm.tsx b/src/components/providers/forms/ProviderForm.tsx index 01f0248..6b6402b 100644 --- a/src/components/providers/forms/ProviderForm.tsx +++ b/src/components/providers/forms/ProviderForm.tsx @@ -171,18 +171,16 @@ export function ProviderForm({ }); // 使用 Base URL hook (Claude, Codex, Gemini) - const { baseUrl, handleClaudeBaseUrlChange, handleGeminiBaseUrlChange } = - useBaseUrlState({ - appType: appId, - category, - settingsConfig: form.watch("settingsConfig"), - codexConfig: "", - onSettingsConfigChange: (config) => - form.setValue("settingsConfig", config), - onCodexConfigChange: () => { - /* noop */ - }, - }); + const { baseUrl, handleClaudeBaseUrlChange } = useBaseUrlState({ + appType: appId, + category, + settingsConfig: form.watch("settingsConfig"), + codexConfig: "", + onSettingsConfigChange: (config) => form.setValue("settingsConfig", config), + onCodexConfigChange: () => { + /* noop */ + }, + }); // 使用 Model hook(新:主模型 + Haiku/Sonnet/Opus 默认模型) const { @@ -317,9 +315,13 @@ export function ProviderForm({ const { geminiEnv, geminiConfig, + geminiApiKey, + geminiBaseUrl, geminiModel, envError, configError: geminiConfigError, + handleGeminiApiKeyChange: originalHandleGeminiApiKeyChange, + handleGeminiBaseUrlChange: originalHandleGeminiBaseUrlChange, handleGeminiEnvChange, handleGeminiConfigChange, resetGeminiConfig, @@ -329,6 +331,39 @@ export function ProviderForm({ initialData: appId === "gemini" ? initialData : undefined, }); + // 包装 Gemini handlers 以同步 settingsConfig + const handleGeminiApiKeyChange = useCallback( + (key: string) => { + originalHandleGeminiApiKeyChange(key); + // 同步更新 settingsConfig + try { + const config = JSON.parse(form.watch("settingsConfig") || "{}"); + if (!config.env) config.env = {}; + config.env.GEMINI_API_KEY = key.trim(); + form.setValue("settingsConfig", JSON.stringify(config, null, 2)); + } catch { + // ignore + } + }, + [originalHandleGeminiApiKeyChange, form], + ); + + const handleGeminiBaseUrlChange = useCallback( + (url: string) => { + originalHandleGeminiBaseUrlChange(url); + // 同步更新 settingsConfig + try { + const config = JSON.parse(form.watch("settingsConfig") || "{}"); + if (!config.env) config.env = {}; + config.env.GOOGLE_GEMINI_BASE_URL = url.trim().replace(/\/+$/, ""); + form.setValue("settingsConfig", JSON.stringify(config, null, 2)); + } catch { + // ignore + } + }, + [originalHandleGeminiBaseUrlChange, form], + ); + // 使用 Gemini 通用配置 hook (仅 Gemini 模式) const { useCommonConfig: useGeminiCommonConfigFlag, @@ -704,15 +739,15 @@ export function ProviderForm({ form.watch("settingsConfig"), isEditMode, )} - apiKey={apiKey} - onApiKeyChange={handleApiKeyChange} + apiKey={geminiApiKey} + onApiKeyChange={handleGeminiApiKeyChange} category={category} shouldShowApiKeyLink={shouldShowGeminiApiKeyLink} websiteUrl={geminiWebsiteUrl} isPartner={isGeminiPartner} partnerPromotionKey={geminiPartnerPromotionKey} shouldShowSpeedTest={shouldShowSpeedTest} - baseUrl={baseUrl} + baseUrl={geminiBaseUrl} onBaseUrlChange={handleGeminiBaseUrlChange} isEndpointModalOpen={isEndpointModalOpen} onEndpointModalToggle={setIsEndpointModalOpen}