diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarModelSettings.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarModelSettings.tsx index ed0ce6ce..769edc3a 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarModelSettings.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarModelSettings.tsx @@ -3,10 +3,12 @@ * Void Editor additions licensed under the AGPLv3 License. *--------------------------------------------------------------------------------------------*/ +import { useEffect, useRef } from 'react' import { FeatureName, featureNames, ProviderName, providerNames } from '../../../../../../../platform/void/common/voidConfigTypes.js' import { useConfigState, useService } from '../util/services.js' import ErrorBoundary from './ErrorBoundary.js' import { VoidSelectBox } from './inputs.js' +import { SelectBox } from '../../../../../../../base/browser/ui/selectBox/selectBox.js' @@ -30,6 +32,28 @@ export const SidebarModelSettingsForFeature = ({ featureName }: { featureName: F models.push(['Provider', 'Model']) } + const selectBoxRef = useRef(null) + + useEffect(() => { + // this is really just to sync the state on initial mount, when init value hasn't been set yet + let synced = false + const syncStateOnMount = () => { + if (!selectBoxRef.current) return + if (synced) return + synced = true + const settingsAtProvider = voidConfigService.state.modelSelectionOfFeature[featureName] + const index = models.findIndex(v => v[0] === settingsAtProvider?.providerName && v[1] === settingsAtProvider?.modelName) + if (index !== -1) + selectBoxRef.current.select(index) + } + syncStateOnMount() + synced = false // sync the next time state changes (but not after that - the "current.value = ..." triggers a state change, causing an infinite loop!) + const disposable = voidConfigService.onDidChangeState(syncStateOnMount) + return () => disposable.dispose() + }, [selectBoxRef, voidConfigService, models, featureName]) + + + return <>

{featureName}

{ @@ -37,7 +61,7 @@ export const SidebarModelSettingsForFeature = ({ featureName }: { featureName: F initVal={models[0]} options={wasEmpty ? [{ text: 'Please add a Provider!', value: models[0] }] : models.map(s => ({ text: s.join(' - '), value: s }))} onChangeSelection={(newVal) => { voidConfigService.setModelSelectionOfFeature(featureName, { providerName: newVal[0] as ProviderName, modelName: newVal[1] }) }} - selectBoxRef={{ current: null }} + selectBoxRef={selectBoxRef} />} {/*

Settings - {featureName}

*/} diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarProviderSettings.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarProviderSettings.tsx index 55d0077b..8e0fe201 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarProviderSettings.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarProviderSettings.tsx @@ -18,6 +18,7 @@ const Setting = ({ providerName, settingName }: { providerName: ProviderName, se const instanceRef = useRef(null) + // set init val to the current state useEffect(() => { // this is really just to sync the state on initial mount, when init value hasn't been set yet let synced = false @@ -32,14 +33,14 @@ const Setting = ({ providerName, settingName }: { providerName: ProviderName, se const stateVal = settingsAtProvider[settingName] if (instanceRef.current.value !== stateVal) { - instanceRef.current.value = stateVal // triggers onDidChangeState + instanceRef.current.value = stateVal // triggers onChangeText } } syncStateOnMount() synced = false // sync the next time state changes (but not after that - the "current.value = ..." triggers a state change, causing an infinite loop!) const disposable = voidConfigService.onDidChangeState(syncStateOnMount) return () => disposable.dispose() - }, [instanceRef, voidConfigService]) + }, [instanceRef, voidConfigService, providerName, settingName]) return <>

{title}

diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/inputs.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/inputs.tsx index d8174ea8..4ed9e919 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/inputs.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/inputs.tsx @@ -50,7 +50,6 @@ export const VoidInputBox = ({ onChangeText, onCreateInstance, placeholder, mult const contextViewProvider = useService('contextViewService'); - return [ @@ -91,52 +90,54 @@ export const VoidInputBox = ({ onChangeText, onCreateInstance, placeholder, mult + export const VoidSelectBox = ({ onChangeSelection, initVal, selectBoxRef, options }: { initVal: T; selectBoxRef: React.MutableRefObject; options: readonly { text: string, value: T }[]; onChangeSelection: (value: T) => void; - }) => { - const containerRef = useRef(null); const contextViewProvider = useService('contextViewService'); - useEffect(() => { - if (!containerRef.current) return; + let containerRef = useRef(null); - const defaultIndex = options.findIndex(opt => opt.value === initVal); + return { + containerRef.current = container + const defaultIndex = options.findIndex(opt => opt.value === initVal); + return [ + options.map(opt => ({ text: opt.text })), + defaultIndex, + contextViewProvider, + unthemedSelectBoxStyles + ] as const; + }, [containerRef, options, initVal, contextViewProvider])} - selectBoxRef.current = new SelectBox( - options.map(opt => ({ text: opt.text })), - defaultIndex, - contextViewProvider, - unthemedSelectBoxStyles - ); + dispose={useCallback((instance: SelectBox) => { + instance.dispose(); + for (let child of containerRef.current?.childNodes ?? []) + containerRef.current?.removeChild(child) + }, [containerRef])} - selectBoxRef.current.render(containerRef.current); + onCreateInstance={useCallback((instance: SelectBox) => { + selectBoxRef.current = instance; + if (containerRef.current) instance.render(containerRef.current) + const disposables = [ + instance.onDidSelect(e => { + console.log('e.selected', JSON.stringify(e)); + onChangeSelection(options[e.index].value); + }) + ]; + return disposables; + }, [containerRef, selectBoxRef, options, onChangeSelection])} - selectBoxRef.current.onDidSelect(e => { console.log('e.selected', JSON.stringify(e)); onChangeSelection(options[e.index].value); }); - - // cleanup - return () => { - if (selectBoxRef.current) { - selectBoxRef.current.dispose(); - if (containerRef.current) { - while (containerRef.current.firstChild) { - containerRef.current.removeChild(containerRef.current.firstChild); - } - } - } - }; - }, [options, initVal, onChangeSelection, contextViewProvider, selectBoxRef]); - - return
; + />; }; - // export const VoidCheckBox = ({ onChangeChecked, initVal, label, checkboxRef, }: { // onChangeChecked: (checked: boolean) => void; // initVal: boolean;