Skip to content

Commit fd91d9f

Browse files
committed
feat: show loading spinner while fetching settings
1 parent 637f4e5 commit fd91d9f

File tree

1 file changed

+29
-17
lines changed

1 file changed

+29
-17
lines changed

src/browser/components/Settings/sections/ModelsSection.tsx

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useState, useEffect, useCallback } from "react";
2-
import { Plus, Trash2, Pencil, Check, X } from "lucide-react";
2+
import { Plus, Trash2, Pencil, Check, X, Loader2 } from "lucide-react";
33
import type { ProvidersConfigMap } from "../types";
44
import { SUPPORTED_PROVIDERS, PROVIDER_DISPLAY_NAMES } from "@/common/constants/providers";
55

@@ -15,7 +15,7 @@ interface EditingState {
1515
}
1616

1717
export function ModelsSection() {
18-
const [config, setConfig] = useState<ProvidersConfigMap>({});
18+
const [config, setConfig] = useState<ProvidersConfigMap | null>(null);
1919
const [newModel, setNewModel] = useState<NewModelForm>({ provider: "", modelId: "" });
2020
const [saving, setSaving] = useState(false);
2121
const [editing, setEditing] = useState<EditingState | null>(null);
@@ -29,30 +29,18 @@ export function ModelsSection() {
2929
})();
3030
}, []);
3131

32-
// Get all custom models across providers
33-
const getAllModels = (): Array<{ provider: string; modelId: string }> => {
34-
const models: Array<{ provider: string; modelId: string }> = [];
35-
for (const [provider, providerConfig] of Object.entries(config)) {
36-
if (providerConfig.models) {
37-
for (const modelId of providerConfig.models) {
38-
models.push({ provider, modelId });
39-
}
40-
}
41-
}
42-
return models;
43-
};
44-
4532
// Check if a model already exists (for duplicate prevention)
4633
const modelExists = useCallback(
4734
(provider: string, modelId: string, excludeOriginal?: string): boolean => {
35+
if (!config) return false;
4836
const currentModels = config[provider]?.models ?? [];
4937
return currentModels.some((m) => m === modelId && m !== excludeOriginal);
5038
},
5139
[config]
5240
);
5341

5442
const handleAddModel = useCallback(async () => {
55-
if (!newModel.provider || !newModel.modelId.trim()) return;
43+
if (!config || !newModel.provider || !newModel.modelId.trim()) return;
5644

5745
const trimmedModelId = newModel.modelId.trim();
5846

@@ -84,6 +72,7 @@ export function ModelsSection() {
8472

8573
const handleRemoveModel = useCallback(
8674
async (provider: string, modelId: string) => {
75+
if (!config) return;
8776
setSaving(true);
8877
try {
8978
const currentModels = config[provider]?.models ?? [];
@@ -115,7 +104,7 @@ export function ModelsSection() {
115104
}, []);
116105

117106
const handleSaveEdit = useCallback(async () => {
118-
if (!editing) return;
107+
if (!config || !editing) return;
119108

120109
const trimmedModelId = editing.newModelId.trim();
121110
if (!trimmedModelId) {
@@ -153,6 +142,29 @@ export function ModelsSection() {
153142
}
154143
}, [editing, config, modelExists]);
155144

145+
// Show loading state while config is being fetched
146+
if (config === null) {
147+
return (
148+
<div className="flex items-center justify-center gap-2 py-12">
149+
<Loader2 className="text-muted h-5 w-5 animate-spin" />
150+
<span className="text-muted text-sm">Loading settings...</span>
151+
</div>
152+
);
153+
}
154+
155+
// Get all custom models across providers
156+
const getAllModels = (): Array<{ provider: string; modelId: string }> => {
157+
const models: Array<{ provider: string; modelId: string }> = [];
158+
for (const [provider, providerConfig] of Object.entries(config)) {
159+
if (providerConfig.models) {
160+
for (const modelId of providerConfig.models) {
161+
models.push({ provider, modelId });
162+
}
163+
}
164+
}
165+
return models;
166+
};
167+
156168
const allModels = getAllModels();
157169

158170
return (

0 commit comments

Comments
 (0)