Skip to content

Commit 2cce257

Browse files
committed
🤖 fix: Settings modal header heights and custom models in selector
- Fixed header height inconsistency by using explicit h-12 class for both sidebar and content headers - Custom models from Settings now appear in model selector dropdown - Added providers-config-changed event to sync models when settings change - Used useMemo for allModels to avoid unnecessary re-renders
1 parent 2f779f2 commit 2cce257

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

src/browser/components/Settings/SettingsModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export function SettingsModal() {
6767
>
6868
{/* Sidebar */}
6969
<div className="border-border-medium flex w-48 shrink-0 flex-col border-r">
70-
<div className="border-border-medium flex items-center justify-between border-b px-4 py-3">
70+
<div className="border-border-medium flex h-12 items-center border-b px-4">
7171
<h2 id="settings-title" className="text-foreground text-sm font-semibold">
7272
Settings
7373
</h2>
@@ -93,7 +93,7 @@ export function SettingsModal() {
9393

9494
{/* Content */}
9595
<div className="flex flex-1 flex-col overflow-hidden">
96-
<div className="border-border-medium flex items-center justify-between border-b px-6 py-3">
96+
<div className="border-border-medium flex h-12 items-center justify-between border-b px-6">
9797
<h3 className="text-foreground text-sm font-medium">{currentSection.label}</h3>
9898
<button
9999
type="button"

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ export function ModelsSection() {
4848
const cfg = await window.api.providers.getConfig();
4949
setConfig(cfg);
5050
setNewModel({ provider: "", modelId: "" });
51+
52+
// Notify other components about the change
53+
window.dispatchEvent(new Event("providers-config-changed"));
5154
} finally {
5255
setSaving(false);
5356
}
@@ -65,6 +68,9 @@ export function ModelsSection() {
6568
// Refresh config
6669
const cfg = await window.api.providers.getConfig();
6770
setConfig(cfg);
71+
72+
// Notify other components about the change
73+
window.dispatchEvent(new Event("providers-config-changed"));
6874
} finally {
6975
setSaving(false);
7076
}

src/browser/hooks/useModelLRU.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useEffect } from "react";
1+
import { useCallback, useEffect, useMemo, useState } from "react";
22
import { usePersistedState, readPersistedState, updatePersistedState } from "./usePersistedState";
33
import { MODEL_ABBREVIATIONS } from "@/browser/utils/slashCommands/registry";
44
import { defaultModel } from "@/common/utils/ai/models";
@@ -42,13 +42,15 @@ export function getDefaultModel(): string {
4242
* Hook to manage a Least Recently Used (LRU) cache of AI models.
4343
* Stores up to 8 recently used models in localStorage.
4444
* Initializes with default abbreviated models if empty.
45+
* Also includes custom models configured in Settings.
4546
*/
4647
export function useModelLRU() {
4748
const [recentModels, setRecentModels] = usePersistedState<string[]>(
4849
LRU_KEY,
4950
DEFAULT_MODELS.slice(0, MAX_LRU_SIZE),
5051
{ listener: true }
5152
);
53+
const [customModels, setCustomModels] = useState<string[]>([]);
5254

5355
const [defaultModel, setDefaultModel] = usePersistedState<string>(
5456
DEFAULT_MODEL_KEY,
@@ -70,6 +72,44 @@ export function useModelLRU() {
7072
// eslint-disable-next-line react-hooks/exhaustive-deps
7173
}, []); // Only run once on mount
7274

75+
// Fetch custom models from providers config
76+
useEffect(() => {
77+
const fetchCustomModels = async () => {
78+
try {
79+
const config = await window.api.providers.getConfig();
80+
const models: string[] = [];
81+
for (const [provider, providerConfig] of Object.entries(config)) {
82+
if (providerConfig.models) {
83+
for (const modelId of providerConfig.models) {
84+
// Format as provider:modelId for consistency
85+
models.push(`${provider}:${modelId}`);
86+
}
87+
}
88+
}
89+
setCustomModels(models);
90+
} catch {
91+
// Ignore errors fetching custom models
92+
}
93+
};
94+
void fetchCustomModels();
95+
96+
// Listen for settings changes via custom event
97+
const handleSettingsChange = () => void fetchCustomModels();
98+
window.addEventListener("providers-config-changed", handleSettingsChange);
99+
return () => window.removeEventListener("providers-config-changed", handleSettingsChange);
100+
}, []);
101+
102+
// Combine LRU models with custom models (custom models appended, deduplicated)
103+
const allModels = useMemo(() => {
104+
const combined = [...recentModels];
105+
for (const model of customModels) {
106+
if (!combined.includes(model)) {
107+
combined.push(model);
108+
}
109+
}
110+
return combined;
111+
}, [recentModels, customModels]);
112+
73113
/**
74114
* Add a model to the LRU cache. If it already exists, move it to the front.
75115
* If the cache is full, remove the least recently used model.
@@ -94,8 +134,8 @@ export function useModelLRU() {
94134
* Get the list of recently used models, most recent first.
95135
*/
96136
const getRecentModels = useCallback(() => {
97-
return recentModels;
98-
}, [recentModels]);
137+
return allModels;
138+
}, [allModels]);
99139

100140
const evictModel = useCallback((modelString: string) => {
101141
if (!modelString.trim()) {
@@ -108,7 +148,7 @@ export function useModelLRU() {
108148
addModel,
109149
evictModel,
110150
getRecentModels,
111-
recentModels,
151+
recentModels: allModels,
112152
defaultModel,
113153
setDefaultModel,
114154
};

0 commit comments

Comments
 (0)