From b47a8b1ea69c41555222ae585cd63bdd2f68a48c Mon Sep 17 00:00:00 2001 From: celestial-vault Date: Sat, 19 Jul 2025 10:22:35 -0700 Subject: [PATCH] fix stale state in model picker searchTerm --- src/core/storage/state.ts | 2 ++ .../components/settings/GroqModelPicker.tsx | 6 +++++ .../settings/HuggingFaceModelPicker.tsx | 27 +++++++++++++++++-- .../settings/OpenRouterModelPicker.tsx | 25 +++++------------ 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/core/storage/state.ts b/src/core/storage/state.ts index 12d8a1500e..644ff22f23 100644 --- a/src/core/storage/state.ts +++ b/src/core/storage/state.ts @@ -528,6 +528,8 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) { actModeSapAiCoreModelId, actModeGroqModelId, actModeGroqModelInfo, + actModeHuggingFaceModelId, + actModeHuggingFaceModelInfo, }, isNewUser: isNewUser ?? true, welcomeViewCompleted, diff --git a/webview-ui/src/components/settings/GroqModelPicker.tsx b/webview-ui/src/components/settings/GroqModelPicker.tsx index 17ef863bb5..fc48964091 100644 --- a/webview-ui/src/components/settings/GroqModelPicker.tsx +++ b/webview-ui/src/components/settings/GroqModelPicker.tsx @@ -67,6 +67,12 @@ const GroqModelPicker: React.FC = ({ isPopup, currentMode }) }) + // Sync external changes when the modelId changes + useEffect(() => { + const currentModelId = modeFields.groqModelId || groqDefaultModelId + setSearchTerm(currentModelId) + }, [modeFields.groqModelId]) + // Debounce search term to reduce re-renders useEffect(() => { const timer = setTimeout(() => { diff --git a/webview-ui/src/components/settings/HuggingFaceModelPicker.tsx b/webview-ui/src/components/settings/HuggingFaceModelPicker.tsx index f529a48a42..ebd0dba64e 100644 --- a/webview-ui/src/components/settings/HuggingFaceModelPicker.tsx +++ b/webview-ui/src/components/settings/HuggingFaceModelPicker.tsx @@ -63,6 +63,12 @@ const HuggingFaceModelPicker: React.FC = ({ isPopup }) }) + // Sync external changes when the modelId changes + useEffect(() => { + const currentModelId = modeFields.huggingFaceModelId || huggingFaceDefaultModelId + setSearchTerm(currentModelId) + }, [modeFields.huggingFaceModelId]) + useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { @@ -173,8 +179,25 @@ const HuggingFaceModelPicker: React.FC = ({ isPopup }} onFocus={() => setIsDropdownVisible(true)} onKeyDown={handleKeyDown} - className="w-full relative z-[1000]" - /> + className="w-full relative z-[1000]"> + {searchTerm && ( +
{ + setSearchTerm("") + setIsDropdownVisible(true) + }} + slot="end" + style={{ + display: "flex", + justifyContent: "center", + alignItems: "center", + height: "100%", + }} + /> + )} + {isDropdownVisible && (
= ({ isPopup, const { apiConfiguration, openRouterModels, refreshOpenRouterModels } = useExtensionState() const modeFields = getModeSpecificFields(apiConfiguration, currentMode) const [searchTerm, setSearchTerm] = useState(modeFields.openRouterModelId || openRouterDefaultModelId) - const [isSearchInputDirty, setIsSearchInputDirty] = useState(false) const [isDropdownVisible, setIsDropdownVisible] = useState(false) const [selectedIndex, setSelectedIndex] = useState(-1) const dropdownRef = useRef(null) @@ -98,22 +97,11 @@ const OpenRouterModelPicker: React.FC = ({ isPopup, useMount(refreshOpenRouterModels) - // Sync external changes only when user isn't actively typing + // Sync external changes when the modelId changes useEffect(() => { - if (!isSearchInputDirty) { - const currentModelId = modeFields.openRouterModelId || openRouterDefaultModelId - setSearchTerm(currentModelId) - } - }, [modeFields.openRouterModelId, isSearchInputDirty]) - - // Reset dirty flag after user stops typing (1 second timeout) - useEffect(() => { - if (!isSearchInputDirty) return - const timeout = setTimeout(() => { - setIsSearchInputDirty(false) - }, 1000) - return () => clearTimeout(timeout) - }, [searchTerm, isSearchInputDirty]) + const currentModelId = modeFields.openRouterModelId || openRouterDefaultModelId + setSearchTerm(currentModelId) + }, [modeFields.openRouterModelId]) useEffect(() => { const handleClickOutside = (event: MouseEvent) => { @@ -269,8 +257,7 @@ const OpenRouterModelPicker: React.FC = ({ isPopup, placeholder="Search and select a model..." value={searchTerm} onInput={(e) => { - setIsSearchInputDirty(true) - handleModelChange((e.target as HTMLInputElement)?.value?.toLowerCase()) + setSearchTerm((e.target as HTMLInputElement)?.value.toLowerCase() || "") setIsDropdownVisible(true) }} onFocus={() => setIsDropdownVisible(true)} @@ -285,7 +272,7 @@ const OpenRouterModelPicker: React.FC = ({ isPopup, className="input-icon-button codicon codicon-close" aria-label="Clear search" onClick={() => { - handleModelChange("") + setSearchTerm("") setIsDropdownVisible(true) }} slot="end"