1- import { createMemo , onCleanup , onMount , type Accessor } from "solid-js"
1+ import { createMemo , createResource , onCleanup , onMount , type Accessor } from "solid-js"
22import type { ColorScheme } from "@opencode-ai/ui/theme/context"
33import { useTheme } from "@opencode-ai/ui/theme/context"
44import {
@@ -14,6 +14,57 @@ import {
1414 useSettings ,
1515} from "@/context/settings"
1616import { playSoundById , SOUND_OPTIONS } from "@/utils/sound"
17+ import { useServerSync } from "@/context/server-sync"
18+
19+ type ShellOption = {
20+ path : string
21+ name : string
22+ acceptable : boolean
23+ }
24+
25+ type ShellSelectOption = {
26+ id : string
27+ value : string
28+ name : string
29+ terminalOnly : boolean
30+ }
31+
32+ export function createShellOptions ( input : { shells : ShellOption [ ] ; current : string | undefined } ) {
33+ const counts = input . shells . reduce ( ( result , shell ) => {
34+ result . set ( shell . name , ( result . get ( shell . name ) ?? 0 ) + 1 )
35+ return result
36+ } , new Map < string , number > ( ) )
37+ const options : ShellSelectOption [ ] = [
38+ { id : "auto" , value : "" , name : "" , terminalOnly : false } ,
39+ ...input . shells . map ( ( shell ) => {
40+ const ambiguous = ( counts . get ( shell . name ) ?? 0 ) > 1
41+ return {
42+ id : shell . path ,
43+ value : ambiguous ? shell . path : shell . name ,
44+ name : ambiguous ? shell . path : shell . name ,
45+ terminalOnly : ! shell . acceptable ,
46+ }
47+ } ) ,
48+ ]
49+ if ( input . current && ! options . some ( ( option ) => option . value === input . current ) ) {
50+ options . push ( { id : input . current , value : input . current , name : input . current , terminalOnly : false } )
51+ }
52+ return options
53+ }
54+
55+ export function createShellSettingsController ( ) {
56+ const serverSync = useServerSync ( )
57+ const [ shells ] = createResource ( async ( ) => [ ] as ShellOption [ ] , { initialValue : [ ] as ShellOption [ ] } )
58+ const current = createMemo ( ( ) => serverSync ( ) . data . config . shell ?? "" )
59+ return {
60+ shells : ( ) => shells . latest ,
61+ current,
62+ select : ( value : string ) => {
63+ if ( value === current ( ) ) return
64+ void serverSync ( ) . updateConfig ( { shell : value } )
65+ } ,
66+ }
67+ }
1768
1869export function createAppearanceSettingsController ( ) {
1970 const settings = useSettings ( )
@@ -86,19 +137,33 @@ export function createSoundSettingsController() {
86137 } ,
87138 } )
88139 return {
89- agent : channel ( settings . sounds . agentEnabled , settings . sounds . agent , settings . sounds . setAgentEnabled , settings . sounds . setAgent ) ,
140+ agent : channel (
141+ settings . sounds . agentEnabled ,
142+ settings . sounds . agent ,
143+ settings . sounds . setAgentEnabled ,
144+ settings . sounds . setAgent ,
145+ ) ,
90146 permissions : channel (
91147 settings . sounds . permissionsEnabled ,
92148 settings . sounds . permissions ,
93149 settings . sounds . setPermissionsEnabled ,
94150 settings . sounds . setPermissions ,
95151 ) ,
96- errors : channel ( settings . sounds . errorsEnabled , settings . sounds . errors , settings . sounds . setErrorsEnabled , settings . sounds . setErrors ) ,
152+ errors : channel (
153+ settings . sounds . errorsEnabled ,
154+ settings . sounds . errors ,
155+ settings . sounds . setErrorsEnabled ,
156+ settings . sounds . setErrors ,
157+ ) ,
97158 }
98159}
99160
100161function soundPreview ( ) {
101- const state = { cleanup : undefined as ( ( ) => void ) | undefined , timeout : undefined as NodeJS . Timeout | undefined , run : 0 }
162+ const state = {
163+ cleanup : undefined as ( ( ) => void ) | undefined ,
164+ timeout : undefined as NodeJS . Timeout | undefined ,
165+ run : 0 ,
166+ }
102167 const stop = ( ) => {
103168 state . run += 1
104169 state . cleanup ?.( )
0 commit comments