From 1a0872c15369e36482bdfe6029f4177ced8d62a2 Mon Sep 17 00:00:00 2001 From: Jason Date: Sun, 18 Jan 2026 21:52:44 +0800 Subject: [PATCH] fix(opencode): prevent model ID input focus loss on keystroke Use local state + onBlur pattern for ModelIdInput to keep React key stable during editing. Previously, each keystroke changed the object key, causing React to unmount/remount the input and lose focus. --- .../providers/forms/OpenCodeFormFields.tsx | 45 +++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/components/providers/forms/OpenCodeFormFields.tsx b/src/components/providers/forms/OpenCodeFormFields.tsx index 792d7add..34d95c7d 100644 --- a/src/components/providers/forms/OpenCodeFormFields.tsx +++ b/src/components/providers/forms/OpenCodeFormFields.tsx @@ -1,3 +1,4 @@ +import { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { FormLabel } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; @@ -14,6 +15,43 @@ import { ApiKeySection } from "./shared"; import { opencodeNpmPackages } from "@/config/opencodeProviderPresets"; import type { ProviderCategory, OpenCodeModel } from "@/types"; +/** + * Model ID input with local state to prevent focus loss. + * The key prop issue: when Model ID changes, React sees it as a new element + * and unmounts/remounts the input, losing focus. Using local state + onBlur + * keeps the key stable during editing. + */ +function ModelIdInput({ + modelId, + onChange, + placeholder, +}: { + modelId: string; + onChange: (newId: string) => void; + placeholder?: string; +}) { + const [localValue, setLocalValue] = useState(modelId); + + // Sync when external modelId changes (e.g., undo operation) + useEffect(() => { + setLocalValue(modelId); + }, [modelId]); + + return ( + setLocalValue(e.target.value)} + onBlur={() => { + if (localValue !== modelId && localValue.trim()) { + onChange(localValue); + } + }} + placeholder={placeholder} + className="flex-1" + /> + ); +} + interface OpenCodeFormFieldsProps { // NPM Package npm: string; @@ -177,13 +215,12 @@ export function OpenCodeFormFields({
{Object.entries(models).map(([key, model]) => (
- handleModelIdChange(key, e.target.value)} + handleModelIdChange(key, newId)} placeholder={t("opencode.modelId", { defaultValue: "Model ID", })} - className="flex-1" />