mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
add settings UI
This commit is contained in:
parent
d3b862ae91
commit
154a82ab0b
8 changed files with 95 additions and 27 deletions
|
|
@ -47,7 +47,7 @@
|
|||
"icon": "$(history)"
|
||||
},
|
||||
{
|
||||
"command": "void.openSettings",
|
||||
"command": "void.toggleSettings",
|
||||
"title": "Void settings",
|
||||
"icon": "$(settings-gear)"
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
"group": "navigation"
|
||||
},
|
||||
{
|
||||
"command": "void.openSettings",
|
||||
"command": "void.toggleSettings",
|
||||
"when": "view == 'void.viewnumberone'",
|
||||
"group": "navigation"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export class DisplayChangesProvider implements vscode.CodeLensProvider {
|
|||
// used internally by vscode
|
||||
public provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CodeLens[]> {
|
||||
const docUriStr = document.uri.toString()
|
||||
return this._diffsOfDocument[docUriStr].flatMap(diff => diff.lenses)
|
||||
return this._diffsOfDocument[docUriStr]?.flatMap(diff => diff.lenses) ?? []
|
||||
}
|
||||
|
||||
// declared by us, registered with vscode.languages.registerCodeLensProvider()
|
||||
|
|
|
|||
|
|
@ -54,10 +54,6 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
displayChangesProvider.rejectDiff(params)
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('void.openSettings', async () => {
|
||||
vscode.commands.executeCommand('workbench.action.openSettings', '@ext:void.void');
|
||||
}));
|
||||
|
||||
// 5. Receive messages from sidebar
|
||||
webviewProvider.webview.then(
|
||||
webview => {
|
||||
|
|
@ -69,6 +65,9 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
context.subscriptions.push(vscode.commands.registerCommand('void.toggleThreadSelector', async () => {
|
||||
webview.postMessage({ type: 'toggleThreadSelector' } satisfies MessageToSidebar)
|
||||
}))
|
||||
context.subscriptions.push(vscode.commands.registerCommand('void.toggleSettings', async () => {
|
||||
webview.postMessage({ type: 'toggleSettings' } satisfies MessageToSidebar)
|
||||
}));
|
||||
|
||||
// Receive messages in the extension from the sidebar webview (messages are sent using `postMessage`)
|
||||
webview.onDidReceiveMessage(async (m: MessageFromSidebar) => {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ type MessageToSidebar = (
|
|||
| { type: 'allThreads', threads: ChatThreads }
|
||||
| { type: 'startNewThread' }
|
||||
| { type: 'toggleThreadSelector' }
|
||||
| { type: 'toggleSettings' }
|
||||
)
|
||||
|
||||
// sidebar -> editor
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ const Sidebar = () => {
|
|||
setTab('threadSelector')
|
||||
})
|
||||
|
||||
// if they toggled settings
|
||||
useOnVSCodeMessage('toggleSettings', (m) => {
|
||||
if (tab === 'settings')
|
||||
setTab('chat')
|
||||
else
|
||||
setTab('settings')
|
||||
})
|
||||
|
||||
|
||||
// Receive messages from the VSCode extension
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,70 @@
|
|||
import React, { useState } from "react";
|
||||
import { useVoidConfig } from "./contextForConfig";
|
||||
import { configFields, useVoidConfig, VoidConfigField } from "./contextForConfig";
|
||||
|
||||
|
||||
const SettingOfFieldAndParam = ({ field, param }: { field: VoidConfigField, param: string }) => {
|
||||
const { voidConfig, partialVoidConfig, voidConfigInfo, setConfigParam } = useVoidConfig()
|
||||
|
||||
const [val, setVal] = useState<string | undefined>(partialVoidConfig[field]?.[param])
|
||||
|
||||
const { enumArr } = voidConfigInfo[field][param]
|
||||
|
||||
const updateState = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => { setVal(e.target.value); };
|
||||
const commitConfigParam = () => { if (val) setConfigParam(field, param, val); };
|
||||
|
||||
|
||||
// string
|
||||
if (enumArr === undefined) {
|
||||
return (
|
||||
<div>
|
||||
<label>{param}</label>
|
||||
<input
|
||||
type="text"
|
||||
value={val}
|
||||
onChange={updateState}
|
||||
onBlur={commitConfigParam}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
// enum
|
||||
else {
|
||||
return (
|
||||
<div>
|
||||
<label>{param}</label>
|
||||
<select
|
||||
value={val}
|
||||
onChange={updateState}
|
||||
onBlur={commitConfigParam}
|
||||
>
|
||||
{enumArr.map((option) => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const SidebarSettings = () => {
|
||||
|
||||
const { voidConfig, setConfigParam } = useVoidConfig()
|
||||
const { voidConfig, voidConfigInfo } = useVoidConfig()
|
||||
|
||||
const current_field = voidConfig.default['whichApi'] as VoidConfigField
|
||||
const params = Object.keys(voidConfigInfo[current_field])
|
||||
|
||||
|
||||
// only show the settings relevant to the current field
|
||||
|
||||
// voidConfig.default.whichApi
|
||||
|
||||
|
||||
return null
|
||||
|
||||
return (
|
||||
<div>
|
||||
{params.map((param) => (
|
||||
<SettingOfFieldAndParam
|
||||
key={param}
|
||||
field={current_field}
|
||||
param={param}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ const configString = (description: string, defaultVal: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
const configFields = [
|
||||
// fields you can customize (don't forget 'default' - it isn't included here!)
|
||||
export const configFields = [
|
||||
'anthropic',
|
||||
'openAI',
|
||||
'greptile',
|
||||
|
|
@ -253,17 +253,18 @@ const voidConfigInfo: Record<
|
|||
|
||||
// this is the type that comes with metadata like desc, default val, etc
|
||||
type VoidConfigInfo = typeof voidConfigInfo
|
||||
export type VoidConfigField = keyof typeof voidConfigInfo // typeof configFields[number]
|
||||
|
||||
// this is the type that specifies the user's actual config
|
||||
export type PartialVoidConfig = {
|
||||
[K in keyof typeof voidConfigInfo]?: {
|
||||
[P in keyof typeof voidConfigInfo[K]]?: string
|
||||
[P in keyof typeof voidConfigInfo[K]]?: typeof voidConfigInfo[K][P]['defaultVal']
|
||||
}
|
||||
}
|
||||
|
||||
export type VoidConfig = {
|
||||
[K in keyof typeof voidConfigInfo]: {
|
||||
[P in keyof typeof voidConfigInfo[K]]: string
|
||||
[P in keyof typeof voidConfigInfo[K]]: typeof voidConfigInfo[K][P]['defaultVal']
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +272,7 @@ export type VoidConfig = {
|
|||
|
||||
const getVoidConfig = (currentConfig: PartialVoidConfig): VoidConfig => {
|
||||
const config = {} as PartialVoidConfig
|
||||
for (let field of configFields) {
|
||||
for (let field of [...configFields, 'default'] as const) {
|
||||
config[field] = {}
|
||||
for (let prop in voidConfigInfo[field]) {
|
||||
config[field][prop] = currentConfig[field]?.[prop] || voidConfigInfo[field][prop].defaultVal
|
||||
|
|
@ -296,16 +297,20 @@ const useInstantState = <T,>(initVal: T) => {
|
|||
|
||||
|
||||
|
||||
type SetConfigParamType = <K extends VoidConfigField>(field: K, param: keyof VoidConfigInfo[K], newVal: string) => void
|
||||
|
||||
type ConfigValueType = {
|
||||
voidConfig: VoidConfig,
|
||||
setConfigParam: <K extends typeof configFields[number]>(field: K, param: keyof VoidConfigInfo[K], newVal: string) => void
|
||||
voidConfigInfo: VoidConfigInfo,
|
||||
partialVoidConfig: PartialVoidConfig,
|
||||
setConfigParam: SetConfigParamType
|
||||
}
|
||||
|
||||
|
||||
const ConfigContext = createContext<ConfigValueType>(undefined as unknown as ConfigValueType)
|
||||
|
||||
export function ConfigProvider({ children }: { children: ReactNode }) {
|
||||
const [partialVoidConfig, setPartialVoidConfig] = useInstantState<PartialVoidConfig>({}) // only used internally here, and to communicate with the extension
|
||||
const [partialVoidConfig, setPartialVoidConfig] = useInstantState<PartialVoidConfig>({}) // the user's selections
|
||||
const [voidConfig, setVoidConfig] = useState<VoidConfig>(defaultVoidConfig)
|
||||
|
||||
|
||||
|
|
@ -323,6 +328,8 @@ export function ConfigProvider({ children }: { children: ReactNode }) {
|
|||
return (<ConfigContext.Provider
|
||||
value={{
|
||||
voidConfig,
|
||||
voidConfigInfo,
|
||||
partialVoidConfig: partialVoidConfig.current ?? {},
|
||||
setConfigParam: (field, param, newVal) => {
|
||||
const newPartialConfig: PartialVoidConfig = {
|
||||
...partialVoidConfig.current,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ const onetimeCallbacks: { [C in Command]: ((res: any) => void)[] } = {
|
|||
"partialVoidConfig": [],
|
||||
"startNewThread": [],
|
||||
"allThreads": [],
|
||||
"toggleThreadSelector": []
|
||||
"toggleThreadSelector": [],
|
||||
"toggleSettings": [],
|
||||
}
|
||||
|
||||
// messageType -> id -> res
|
||||
|
|
@ -22,7 +23,8 @@ const callbacks: { [C in Command]: { [id: string]: ((res: any) => void) } } = {
|
|||
"partialVoidConfig": {},
|
||||
"startNewThread": {},
|
||||
"allThreads": {},
|
||||
"toggleThreadSelector": {}
|
||||
"toggleThreadSelector": {},
|
||||
"toggleSettings": {},
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue