@@ -5,9 +5,12 @@ import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon"
55import { IconButtonV2 } from "@opencode-ai/ui/v2/icon-button-v2"
66import { TextInputV2 } from "@opencode-ai/ui/v2/text-input-v2"
77import { type Component , For , Show } from "solid-js"
8+ import { createStore } from "solid-js/store"
89import { useLanguage } from "@/context/language"
910import { useModels } from "@/context/models"
11+ import { useServerSDK } from "@/context/server-sdk"
1012import { popularProviders } from "@/hooks/use-providers"
13+ import { Persist , persisted } from "@/utils/persist"
1114import { SettingsListV2 } from "./parts/list"
1215import { SettingsRowV2 } from "./parts/row"
1316import "./settings-v2.css"
@@ -19,6 +22,11 @@ const PROVIDER_ICON_SIZE = 16
1922export const SettingsModelsV2 : Component = ( ) => {
2023 const language = useLanguage ( )
2124 const models = useModels ( )
25+ const serverSdk = useServerSDK ( )
26+ const [ store , setStore ] = persisted (
27+ Persist . serverGlobal ( serverSdk ( ) . scope , "settings-v2.models.providers" ) ,
28+ createStore ( { collapsed : { } as Record < string , boolean > } ) ,
29+ )
2230
2331 const list = useFilteredList < ModelItem > ( {
2432 items : ( _filter ) => models . list ( ) ,
@@ -94,41 +102,82 @@ export const SettingsModelsV2: Component = () => {
94102 }
95103 >
96104 < For each = { list . grouped . latest } >
97- { ( group ) => (
98- < div class = "settings-v2-section" data-component = "settings-models-provider" >
99- < div class = "settings-v2-models-group-header" >
100- < ProviderIcon
101- id = { group . category }
102- width = { PROVIDER_ICON_SIZE }
103- height = { PROVIDER_ICON_SIZE }
104- class = "settings-v2-models-provider-icon shrink-0"
105- />
106- < h3 class = "settings-v2-section-title" > { group . items [ 0 ] . provider . name } </ h3 >
105+ { ( group ) => {
106+ const searching = ( ) => list . filter ( ) . length > 0
107+ const expanded = ( ) => searching ( ) || ! store . collapsed [ group . category ]
108+
109+ return (
110+ < div
111+ class = "settings-v2-section"
112+ data-component = "settings-models-provider"
113+ data-expanded = { expanded ( ) ? "" : undefined }
114+ >
115+ < h3 class = "settings-v2-models-group-header" >
116+ < button
117+ type = "button"
118+ class = "settings-v2-models-group-trigger"
119+ aria-expanded = { expanded ( ) }
120+ disabled = { searching ( ) }
121+ onClick = { ( ) => setStore ( "collapsed" , group . category , expanded ( ) ) }
122+ >
123+ < span class = "settings-v2-models-group-chevron" >
124+ < Show
125+ when = { expanded ( ) }
126+ fallback = {
127+ < svg width = "5" height = "6" viewBox = "0 0 5 6" fill = "none" aria-hidden = "true" >
128+ < path
129+ d = "M0.75194 5.31663C0.41861 5.51103 0 5.27063 0 4.88473V0.500754C0 0.114854 0.41861 -0.125577 0.75194 0.0688635L4.5096 2.26084C4.8404 2.45378 4.8404 2.93168 4.5096 3.12462L0.75194 5.31663Z"
130+ fill = "currentColor"
131+ />
132+ </ svg >
133+ }
134+ >
135+ < svg width = "16" height = "16" viewBox = "0 0 16 16" fill = "none" aria-hidden = "true" >
136+ < path
137+ d = "M5.37624 6.75194C5.18184 6.41861 5.42224 6 5.80814 6H10.1921C10.578 6 10.8184 6.41861 10.624 6.75194L8.43203 10.5096C8.23909 10.8404 7.76119 10.8404 7.56825 10.5096L5.37624 6.75194Z"
138+ fill = "currentColor"
139+ />
140+ </ svg >
141+ </ Show >
142+ </ span >
143+ < span class = "settings-v2-models-group-label" >
144+ < ProviderIcon
145+ id = { group . category }
146+ width = { PROVIDER_ICON_SIZE }
147+ height = { PROVIDER_ICON_SIZE }
148+ class = "settings-v2-models-provider-icon shrink-0"
149+ />
150+ < span class = "settings-v2-section-title" > { group . items [ 0 ] . provider . name } </ span >
151+ </ span >
152+ </ button >
153+ </ h3 >
154+ < Show when = { expanded ( ) } >
155+ < SettingsListV2 >
156+ < For each = { group . items } >
157+ { ( item ) => {
158+ const key = { providerID : item . provider . id , modelID : item . id }
159+ return (
160+ < SettingsRowV2 title = { item . name } description = "" >
161+ < div >
162+ < Switch
163+ checked = { models . visible ( key ) }
164+ onChange = { ( checked ) => {
165+ models . setVisibility ( key , checked )
166+ } }
167+ hideLabel
168+ >
169+ { item . name }
170+ </ Switch >
171+ </ div >
172+ </ SettingsRowV2 >
173+ )
174+ } }
175+ </ For >
176+ </ SettingsListV2 >
177+ </ Show >
107178 </ div >
108- < SettingsListV2 >
109- < For each = { group . items } >
110- { ( item ) => {
111- const key = { providerID : item . provider . id , modelID : item . id }
112- return (
113- < SettingsRowV2 title = { item . name } description = "" >
114- < div >
115- < Switch
116- checked = { models . visible ( key ) }
117- onChange = { ( checked ) => {
118- models . setVisibility ( key , checked )
119- } }
120- hideLabel
121- >
122- { item . name }
123- </ Switch >
124- </ div >
125- </ SettingsRowV2 >
126- )
127- } }
128- </ For >
129- </ SettingsListV2 >
130- </ div >
131- ) }
179+ )
180+ } }
132181 </ For >
133182 </ Show >
134183 </ Show >
0 commit comments