mirror of
https://github.com/voideditor/void
synced 2026-05-24 01:48:25 +00:00
settings styles
This commit is contained in:
parent
597c04f63b
commit
7752278720
4 changed files with 48 additions and 30 deletions
|
|
@ -498,10 +498,10 @@ export const SidebarChat = () => {
|
|||
|
||||
{/* bottom row */}
|
||||
<div
|
||||
className='flex flex-row justify-between items-end'
|
||||
className='flex flex-row justify-between items-end gap-1'
|
||||
>
|
||||
{/* submit options */}
|
||||
<div>
|
||||
<div className='w-[250px]'>
|
||||
<ModelDropdown featureName='Ctrl+L' />
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { useService } from '../util/services.js';
|
||||
import { , InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js';
|
||||
import { IInputBoxStyles, InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js';
|
||||
import { defaultInputBoxStyles, defaultSelectBoxStyles } from '../../../../../../../platform/theme/browser/defaultStyles.js';
|
||||
import { SelectBox } from '../../../../../../../base/browser/ui/selectBox/selectBox.js';
|
||||
import { IDisposable } from '../../../../../../../base/common/lifecycle.js';
|
||||
|
|
@ -14,13 +14,14 @@ import { ScrollableElementCreationOptions } from '../../../../../../../base/brow
|
|||
|
||||
|
||||
|
||||
export const WidgetComponent = <CtorParams extends any[], Instance>({ ctor, propsFn, dispose, onCreateInstance, children }
|
||||
export const WidgetComponent = <CtorParams extends any[], Instance>({ ctor, propsFn, dispose, onCreateInstance, children, className }
|
||||
: {
|
||||
ctor: { new(...params: CtorParams): Instance },
|
||||
propsFn: (container: HTMLDivElement) => CtorParams,
|
||||
onCreateInstance: (instance: Instance) => IDisposable[],
|
||||
dispose: (instance: Instance) => void,
|
||||
children?: React.ReactNode,
|
||||
className?: string
|
||||
}
|
||||
) => {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
|
@ -34,7 +35,7 @@ export const WidgetComponent = <CtorParams extends any[], Instance>({ ctor, prop
|
|||
}
|
||||
}, [ctor, propsFn, dispose, onCreateInstance, containerRef])
|
||||
|
||||
return <div ref={containerRef} className='w-full'>{children}</div>
|
||||
return <div ref={containerRef} className={className === undefined ? `w-full` : className}>{children}</div>
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -105,6 +106,7 @@ export const VoidSelectBox = <T,>({ onChangeSelection, onCreateInstance, selectB
|
|||
let containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
return <WidgetComponent
|
||||
className='text-ellipsis whitespace-nowrap pr-6'
|
||||
ctor={SelectBox}
|
||||
propsFn={useCallback((container) => {
|
||||
containerRef.current = container
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { ProviderName, SettingName, displayInfoOfSettingName, titleOfProviderNam
|
|||
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js'
|
||||
import { VoidInputBox, VoidSelectBox } from '../util/inputs.js'
|
||||
import { useIsDark, useRefreshModelState, useService, useSettingsState } from '../util/services.js'
|
||||
import { X } from 'lucide-react'
|
||||
|
||||
|
||||
|
||||
|
|
@ -18,10 +19,10 @@ const RefreshableModels = () => {
|
|||
if (!settingsState.settingsOfProvider.ollama.enabled)
|
||||
return null
|
||||
|
||||
return <>
|
||||
return <div>
|
||||
<button onClick={() => refreshModelService.refreshOllamaModels()}>refresh Ollama built-in models</button>
|
||||
{refreshModelState === 'loading' ? 'loading...' : 'good!'}
|
||||
</>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -110,16 +111,16 @@ export const ModelDump = () => {
|
|||
const settingsState = useSettingsState()
|
||||
|
||||
// a dump of all the enabled providers' models
|
||||
const modelDump: (ModelInfo & { providerName: ProviderName })[] = []
|
||||
const modelDump: (ModelInfo & { providerName: ProviderName, providerEnabled: boolean })[] = []
|
||||
for (let providerName of providerNames) {
|
||||
const providerSettings = settingsState.settingsOfProvider[providerName]
|
||||
if (!providerSettings.enabled) continue
|
||||
modelDump.push(...providerSettings.models.map(model => ({ ...model, providerName })))
|
||||
// if (!providerSettings.enabled) continue
|
||||
modelDump.push(...providerSettings.models.map(model => ({ ...model, providerName, providerEnabled: providerSettings.enabled })))
|
||||
}
|
||||
|
||||
return <div className=''>
|
||||
{modelDump.map(m => {
|
||||
const { isHidden, isDefault, modelName, providerName } = m
|
||||
const { isHidden, isDefault, modelName, providerName, providerEnabled } = m
|
||||
|
||||
return <div key={`${modelName}${providerName}`} className='flex items-center justify-between gap-4 hover:bg-black/10 dark:hover:bg-gray-200/10 py-1 px-3 rounded-sm overflow-hidden cursor-default'>
|
||||
{/* left part is width:full */}
|
||||
|
|
@ -129,9 +130,9 @@ export const ModelDump = () => {
|
|||
{/* right part is anything that fits */}
|
||||
<div className='w-fit flex items-center gap-4'>
|
||||
<span className='opacity-50 whitespace-nowrap'>{isDefault ? '' : '(custom model)'}</span>
|
||||
<div onClick={() => { settingsStateService.toggleModelHidden(providerName, modelName) }}>{isHidden ? '❌' : '✅'}</div>
|
||||
<div className='w-10'>
|
||||
{isDefault ? null : <button onClick={() => { settingsStateService.deleteModel(providerName, modelName) }}>x</button>}
|
||||
<button disabled={!providerEnabled} onClick={() => { settingsStateService.toggleModelHidden(providerName, modelName) }}>{(!providerEnabled || isHidden) ? '❌' : '✅'}</button>
|
||||
<div className='w-5 flex items-center justify-center'>
|
||||
{isDefault ? null : <button onClick={() => { settingsStateService.deleteModel(providerName, modelName) }}><X className='size-4' /></button>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -190,7 +191,7 @@ const SettingsForProvider = ({ providerName }: { providerName: ProviderName }) =
|
|||
|
||||
<div className='flex items-center gap-4'>
|
||||
<h3 className='text-xl'>{titleOfProviderName(providerName)}</h3>
|
||||
<span onClick={() => { voidSettingsService.setSettingOfProvider(providerName, 'enabled', !enabled) }}>{enabled ? '✅' : '❌'}</span>
|
||||
<button onClick={() => { voidSettingsService.setSettingOfProvider(providerName, 'enabled', !enabled) }}>{enabled ? '✅' : '❌'}</button>
|
||||
</div>
|
||||
{/* settings besides models (e.g. api key) */}
|
||||
{Object.keys(others).map((sName, i) => {
|
||||
|
|
@ -248,7 +249,7 @@ export const Settings = () => {
|
|||
<div className='w-full overflow-y-auto'>
|
||||
|
||||
<div className={`${tab !== 'models' ? 'hidden' : ''}`}>
|
||||
<h2 className={`text-3xl`}>Models</h2>
|
||||
<h2 className={`text-3xl mb-2`}>Models</h2>
|
||||
<ErrorBoundary>
|
||||
<ModelDump />
|
||||
<AddModelButton />
|
||||
|
|
@ -257,7 +258,7 @@ export const Settings = () => {
|
|||
</div>
|
||||
|
||||
<div className={`${tab !== 'providers' ? 'hidden' : ''}`}>
|
||||
<h2 className={`text-3xl`} onClick={() => { setTab('providers') }}>Providers</h2>
|
||||
<h2 className={`text-3xl mb-2`} onClick={() => { setTab('providers') }}>Providers</h2>
|
||||
<ErrorBoundary>
|
||||
<VoidProviderSettings />
|
||||
</ErrorBoundary>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import { mountVoidSettings } from './react/out/void-settings-tsx/index.js'
|
|||
import { getReactServices } from './helpers/reactServicesHelper.js';
|
||||
import { Codicon } from '../../../../base/common/codicons.js';
|
||||
import { IDisposable } from '../../../../base/common/lifecycle.js';
|
||||
import { DomScrollableElement } from '../../../../base/browser/ui/scrollbar/scrollableElement.js';
|
||||
|
||||
|
||||
// refer to preferences.contribution.ts keybindings editor
|
||||
|
|
@ -62,6 +63,8 @@ class VoidSettingsInput extends EditorInput {
|
|||
class VoidSettingsPane extends EditorPane {
|
||||
static readonly ID = 'workbench.test.myCustomPane';
|
||||
|
||||
private _scrollbar: DomScrollableElement | undefined;
|
||||
|
||||
constructor(
|
||||
group: IEditorGroup,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
|
|
@ -73,31 +76,43 @@ class VoidSettingsPane extends EditorPane {
|
|||
}
|
||||
|
||||
protected createEditor(parent: HTMLElement): void {
|
||||
// parent.style.overflow = 'auto'
|
||||
parent.style.userSelect = 'text'
|
||||
parent.style.height = '100%';
|
||||
parent.style.width = '100%';
|
||||
|
||||
const scrollableContent = document.createElement('div');
|
||||
scrollableContent.style.height = '100%';
|
||||
scrollableContent.style.width = '100%';
|
||||
|
||||
// gets set immediately
|
||||
this._scrollbar = this._register(new DomScrollableElement(scrollableContent, {}));
|
||||
parent.appendChild(this._scrollbar.getDomNode());
|
||||
this._scrollbar.scanDomNode();
|
||||
|
||||
// Mount React into the scrollable content
|
||||
this.instantiationService.invokeFunction(accessor => {
|
||||
const services = getReactServices(accessor)
|
||||
const disposables: IDisposable[] | undefined = mountVoidSettings(parent, services);
|
||||
disposables?.forEach(d => this._register(d))
|
||||
})
|
||||
const services = getReactServices(accessor);
|
||||
const disposables: IDisposable[] | undefined = mountVoidSettings(scrollableContent, services);
|
||||
|
||||
setTimeout(() => { // this is a complete hack and I don't really understand how scrollbar works here
|
||||
this._scrollbar?.scanDomNode();
|
||||
}, 1000)
|
||||
disposables?.forEach(d => this._register(d));
|
||||
});
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): void {
|
||||
const container = this.getContainer();
|
||||
if (!container) return;
|
||||
if (!this._scrollbar) return;
|
||||
|
||||
this._scrollbar.getDomNode().style.height = `${dimension.height}px`;
|
||||
this._scrollbar.getDomNode().style.width = `${dimension.width}px`;
|
||||
this._scrollbar.scanDomNode();
|
||||
|
||||
container.style.width = `${dimension.width}px`;
|
||||
container.style.height = `${dimension.height}px`;
|
||||
}
|
||||
|
||||
override get minimumWidth() { return 512 }
|
||||
|
||||
override get minimumWidth() { return 700 }
|
||||
|
||||
}
|
||||
|
||||
|
||||
// register Settings pane
|
||||
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
|
||||
EditorPaneDescriptor.create(VoidSettingsPane, VoidSettingsPane.ID, nls.localize('VoidSettingsPane', "Void Settings Pane")),
|
||||
|
|
|
|||
Loading…
Reference in a new issue