Skip to content

Commit d6a4265

Browse files
committed
fix: eliminate model info flicker during settings save with simple React state cache
Fixes #4430 Replace complex cross-window persistence system with a minimal 3-line React state solution that caches the last known ModelInfo and uses it as a fallback when selectedModelInfo temporarily becomes unavailable during settings save. This simple in-memory approach eliminates the flicker without adding complexity, cross-window coordination, or background revalidation.
1 parent eedc264 commit d6a4265

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ExternalLinkIcon } from "@radix-ui/react-icons"
77
import {
88
type ProviderName,
99
type ProviderSettings,
10+
type ModelInfo,
1011
DEFAULT_CONSECUTIVE_MISTAKE_LIMIT,
1112
openRouterDefaultModelId,
1213
requestyDefaultModelId,
@@ -173,6 +174,9 @@ const ApiOptions = ({
173174
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false)
174175
const [isAdvancedSettingsOpen, setIsAdvancedSettingsOpen] = useState(false)
175176

177+
// Simple cache to prevent flicker during settings save
178+
const [lastKnownModelInfo, setLastKnownModelInfo] = useState<ModelInfo | undefined>()
179+
176180
const handleInputChange = useCallback(
177181
<K extends keyof ProviderSettings, E>(
178182
field: K,
@@ -190,6 +194,16 @@ const ApiOptions = ({
190194
info: selectedModelInfo,
191195
} = useSelectedModel(apiConfiguration)
192196

197+
// Update cache whenever selectedModelInfo is available
198+
useEffect(() => {
199+
if (selectedModelInfo) {
200+
setLastKnownModelInfo(selectedModelInfo)
201+
}
202+
}, [selectedModelInfo])
203+
204+
// Use cached info as fallback when selectedModelInfo is temporarily unavailable
205+
const displayModelInfo = selectedModelInfo || lastKnownModelInfo
206+
193207
const { data: routerModels, refetch: refetchRouterModels } = useRouterModels()
194208

195209
const { data: openRouterModelProviders } = useOpenRouterModelProviders(apiConfiguration?.openRouterModelId, {
@@ -749,11 +763,11 @@ const ApiOptions = ({
749763
)}
750764

751765
{/* Only show model info if not deprecated */}
752-
{!selectedModelInfo?.deprecated && (
766+
{!displayModelInfo?.deprecated && (
753767
<ModelInfoView
754768
apiProvider={selectedProvider}
755769
selectedModelId={selectedModelId}
756-
modelInfo={selectedModelInfo}
770+
modelInfo={displayModelInfo}
757771
isDescriptionExpanded={isDescriptionExpanded}
758772
setIsDescriptionExpanded={setIsDescriptionExpanded}
759773
/>
@@ -773,16 +787,16 @@ const ApiOptions = ({
773787
key={`${selectedProvider}-${selectedModelId}`}
774788
apiConfiguration={apiConfiguration}
775789
setApiConfigurationField={setApiConfigurationField}
776-
modelInfo={selectedModelInfo}
790+
modelInfo={displayModelInfo}
777791
/>
778792
)}
779793

780794
{/* Gate Verbosity UI by capability flag */}
781-
{selectedModelInfo?.supportsVerbosity && (
795+
{displayModelInfo?.supportsVerbosity && (
782796
<Verbosity
783797
apiConfiguration={apiConfiguration}
784798
setApiConfigurationField={setApiConfigurationField}
785-
modelInfo={selectedModelInfo}
799+
modelInfo={displayModelInfo}
786800
/>
787801
)}
788802

@@ -802,12 +816,12 @@ const ApiOptions = ({
802816
fuzzyMatchThreshold={apiConfiguration.fuzzyMatchThreshold}
803817
onChange={(field, value) => setApiConfigurationField(field, value)}
804818
/>
805-
{selectedModelInfo?.supportsTemperature !== false && (
819+
{displayModelInfo?.supportsTemperature !== false && (
806820
<TemperatureControl
807821
value={apiConfiguration.modelTemperature}
808822
onChange={handleInputChange("modelTemperature", noTransform)}
809823
maxValue={2}
810-
defaultValue={selectedModelInfo?.defaultTemperature}
824+
defaultValue={displayModelInfo?.defaultTemperature}
811825
/>
812826
)}
813827
<RateLimitSecondsControl

0 commit comments

Comments
 (0)