mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
add sync state for dropdown
This commit is contained in:
parent
cb2de5505b
commit
a28194c601
3 changed files with 59 additions and 33 deletions
|
|
@ -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<SelectBox | null>(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 <>
|
||||
<h2>{featureName}</h2>
|
||||
{
|
||||
|
|
@ -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}
|
||||
/>}
|
||||
|
||||
{/* <h1>Settings - {featureName}</h1> */}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ const Setting = ({ providerName, settingName }: { providerName: ProviderName, se
|
|||
|
||||
const instanceRef = useRef<InputBox | null>(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 <><ErrorBoundary>
|
||||
<h2>{title}</h2>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ export const VoidInputBox = ({ onChangeText, onCreateInstance, placeholder, mult
|
|||
|
||||
const contextViewProvider = useService('contextViewService');
|
||||
|
||||
|
||||
return <WidgetComponent
|
||||
ctor={InputBox}
|
||||
propsFn={useCallback((container) => [
|
||||
|
|
@ -91,52 +90,54 @@ export const VoidInputBox = ({ onChangeText, onCreateInstance, placeholder, mult
|
|||
|
||||
|
||||
|
||||
|
||||
export const VoidSelectBox = <T,>({ onChangeSelection, initVal, selectBoxRef, options }: {
|
||||
initVal: T;
|
||||
selectBoxRef: React.MutableRefObject<SelectBox | null>;
|
||||
options: readonly { text: string, value: T }[];
|
||||
onChangeSelection: (value: T) => void;
|
||||
|
||||
}) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const contextViewProvider = useService('contextViewService');
|
||||
|
||||
useEffect(() => {
|
||||
if (!containerRef.current) return;
|
||||
let containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const defaultIndex = options.findIndex(opt => opt.value === initVal);
|
||||
return <WidgetComponent
|
||||
ctor={SelectBox}
|
||||
propsFn={useCallback((container) => {
|
||||
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 <div ref={containerRef} className="w-full" />;
|
||||
/>;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// export const VoidCheckBox = ({ onChangeChecked, initVal, label, checkboxRef, }: {
|
||||
// onChangeChecked: (checked: boolean) => void;
|
||||
// initVal: boolean;
|
||||
|
|
|
|||
Loading…
Reference in a new issue