@@ -105,7 +105,8 @@ type CustomModelSectionProps = NewCustomModelSectionProps | ExistingCustomModelS
105105const CustomModelSection = ( { isNew, onChange, model : customModel } : CustomModelSectionProps ) => {
106106 const id = customModel ?. id || "" ;
107107 const [ isEditing , setIsEditing ] = useState ( isNew ) ;
108- const [ isSaving , setIsSaving ] = useState ( false ) ;
108+ const [ isProcessing , setIsProcessing ] = useState ( false ) ;
109+ const [ processingAction , setProcessingAction ] = useState < "save" | "delete" | null > ( null ) ;
109110 const [ baseUrl , setBaseUrl ] = useState ( customModel ?. baseUrl || "" ) ;
110111 const [ slug , setSlug ] = useState ( customModel ?. slug ?? "" ) ;
111112 const [ apiKey , setApiKey ] = useState ( customModel ?. apiKey || "" ) ;
@@ -127,13 +128,13 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
127128 const errorInputClassName = "!border-red-500 focus:!border-red-500" ;
128129
129130 const handleOnChange = async ( isDelete : boolean ) => {
130- if ( isSaving ) return ;
131+ if ( isProcessing ) return ;
132+
133+ const isSaveAction = ! isDelete ;
131134
132135 if (
133- modelName . trim ( ) . length < 1 ||
134- slug . trim ( ) . length < 1 ||
135- baseUrl . trim ( ) . length < 1 ||
136- apiKey . trim ( ) . length < 1
136+ isSaveAction &&
137+ ( modelName . trim ( ) . length < 1 || slug . trim ( ) . length < 1 || baseUrl . trim ( ) . length < 1 || apiKey . trim ( ) . length < 1 )
137138 ) {
138139 setIsModelNameValid ( modelName . trim ( ) . length > 0 ) ;
139140 setIsSlugValid ( slug . trim ( ) . length > 0 ) ;
@@ -142,8 +143,8 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
142143 return ;
143144 }
144145
145- const isSaveAction = ! isDelete ;
146- if ( isSaveAction ) setIsSaving ( true ) ;
146+ setIsProcessing ( true ) ;
147+ setProcessingAction ( isDelete ? "delete" : "save" ) ;
147148
148149 try {
149150 await onChange (
@@ -174,7 +175,8 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
174175 setIsEditing ( false ) ;
175176 }
176177 } finally {
177- if ( isSaveAction ) setIsSaving ( false ) ;
178+ setIsProcessing ( false ) ;
179+ setProcessingAction ( null ) ;
178180 }
179181 } ;
180182
@@ -186,7 +188,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
186188 value = { modelName }
187189 placeholder = "My Model"
188190 type = "text"
189- disabled = { ! isEditing || isSaving }
191+ disabled = { ! isEditing || isProcessing }
190192 onChange = { ( e ) => {
191193 setIsModelNameValid ( true ) ;
192194 setModelName ( e . target . value ) ;
@@ -197,13 +199,13 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
197199 < Tooltip content = "Add" placement = "bottom" className = "noselect" delay = { 500 } >
198200 < button
199201 onClick = { ( ) => handleOnChange ( false ) }
200- disabled = { isSaving }
202+ disabled = { isProcessing }
201203 className = "p-1 hover:bg-default-100 rounded disabled:opacity-60"
202204 >
203205 < Icon
204- icon = { isSaving ? "tabler:loader-2" : "tabler:device-floppy" }
206+ icon = { isProcessing && processingAction === "save" ? "tabler:loader-2" : "tabler:device-floppy" }
205207 width = "16"
206- className = { isSaving ? "animate-spin" : "" }
208+ className = { isProcessing && processingAction === "save" ? "animate-spin" : "" }
207209 />
208210 </ button >
209211 </ Tooltip >
@@ -218,23 +220,33 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
218220 setIsEditing ( true ) ;
219221 }
220222 } }
221- disabled = { isSaving }
223+ disabled = { isProcessing }
222224 className = "p-1 hover:bg-default-100 rounded disabled:opacity-60"
223225 >
224226 < Icon
225- icon = { isEditing ? ( isSaving ? "tabler:loader-2" : "tabler:device-floppy" ) : "tabler:pencil" }
227+ icon = {
228+ isEditing
229+ ? isProcessing && processingAction === "save"
230+ ? "tabler:loader-2"
231+ : "tabler:device-floppy"
232+ : "tabler:pencil"
233+ }
226234 width = "16"
227- className = { isEditing && isSaving ? "animate-spin" : "" }
235+ className = { isEditing && isProcessing && processingAction === "save" ? "animate-spin" : "" }
228236 />
229237 </ button >
230238 </ Tooltip >
231239 < Tooltip content = "Delete" placement = "bottom" className = "noselect" delay = { 500 } >
232240 < button
233241 onClick = { ( ) => handleOnChange ( true ) }
234- disabled = { isSaving }
242+ disabled = { isProcessing }
235243 className = "p-1 hover:bg-default-100 rounded disabled:opacity-60"
236244 >
237- < Icon icon = "tabler:trash" width = "16" />
245+ < Icon
246+ icon = { isProcessing && processingAction === "delete" ? "tabler:loader-2" : "tabler:trash" }
247+ width = "16"
248+ className = { isProcessing && processingAction === "delete" ? "animate-spin" : "" }
249+ />
238250 </ button >
239251 </ Tooltip >
240252 </ div >
@@ -248,7 +260,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
248260 value = { slug }
249261 placeholder = "e.g., gemini-2.5-flash"
250262 type = "text"
251- disabled = { ! isEditing || isSaving }
263+ disabled = { ! isEditing || isProcessing }
252264 onChange = { ( e ) => {
253265 setIsSlugValid ( true ) ;
254266 setSlug ( e . target . value ) ;
@@ -263,7 +275,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
263275 value = { baseUrl }
264276 placeholder = "An OpenAI-compatible endpoint"
265277 type = "text"
266- disabled = { ! isEditing || isSaving }
278+ disabled = { ! isEditing || isProcessing }
267279 onChange = { ( e ) => {
268280 setIsBaseUrlValid ( true ) ;
269281 setBaseUrl ( e . target . value ) ;
@@ -278,7 +290,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
278290 value = { apiKey }
279291 placeholder = "Your API Key"
280292 type = { ! isEditing && ! isNew ? "password" : "text" }
281- disabled = { ! isEditing || isSaving }
293+ disabled = { ! isEditing || isProcessing }
282294 onChange = { ( e ) => {
283295 setIsApiKeyValid ( true ) ;
284296 setApiKey ( e . target . value ) ;
@@ -305,7 +317,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
305317 type = "number"
306318 min = { 0 }
307319 step = "1"
308- disabled = { ! isEditing || isSaving }
320+ disabled = { ! isEditing || isProcessing }
309321 onChange = { ( e ) => setContextWindow ( e . target . value === "" ? 0 : Math . trunc ( Number ( e . target . value ) ) ) }
310322 />
311323 </ div >
@@ -318,7 +330,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
318330 type = "number"
319331 min = { 0 }
320332 step = "1"
321- disabled = { ! isEditing || isSaving }
333+ disabled = { ! isEditing || isProcessing }
322334 onChange = { ( e ) => setMaxOutput ( e . target . value === "" ? 0 : Math . trunc ( Number ( e . target . value ) ) ) }
323335 />
324336 </ div >
@@ -331,7 +343,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
331343 type = "number"
332344 min = { 0 }
333345 step = "1"
334- disabled = { ! isEditing || isSaving }
346+ disabled = { ! isEditing || isProcessing }
335347 onChange = { ( e ) => setInputPrice ( e . target . value === "" ? 0 : Math . trunc ( Number ( e . target . value ) ) ) }
336348 />
337349 </ div >
@@ -345,7 +357,7 @@ const CustomModelSection = ({ isNew, onChange, model: customModel }: CustomModel
345357 min = { 0 }
346358 step = "1"
347359 pattern = "[0-9]*"
348- disabled = { ! isEditing || isSaving }
360+ disabled = { ! isEditing || isProcessing }
349361 onChange = { ( e ) => setOutputPrice ( e . target . value === "" ? 0 : Math . trunc ( Number ( e . target . value ) ) ) }
350362 />
351363 </ div >
0 commit comments