diff --git a/src/vs/workbench/contrib/void/browser/helpers/reactServicesHelper.ts b/src/vs/workbench/contrib/void/browser/helpers/reactServicesHelper.ts
index 3c043344..08ad3fdb 100644
--- a/src/vs/workbench/contrib/void/browser/helpers/reactServicesHelper.ts
+++ b/src/vs/workbench/contrib/void/browser/helpers/reactServicesHelper.ts
@@ -9,10 +9,12 @@ import { ILLMMessageService } from '../../../../../platform/void/common/llmMessa
import { IRefreshModelService } from '../../../../../platform/void/common/refreshModelService.js';
import { IVoidSettingsService } from '../../../../../platform/void/common/voidSettingsService.js';
import { IInlineDiffsService } from '../inlineDiffsService.js';
+import { IQuickEditStateService } from '../quickEditStateService.js';
import { ISidebarStateService } from '../sidebarStateService.js';
import { IThreadHistoryService } from '../threadHistoryService.js';
export type ReactServicesType = {
+ quickEditStateService: IQuickEditStateService;
sidebarStateService: ISidebarStateService;
settingsStateService: IVoidSettingsService;
threadsStateService: IThreadHistoryService;
@@ -33,6 +35,7 @@ export type ReactServicesType = {
export const getReactServices = (accessor: ServicesAccessor): ReactServicesType => {
return {
+ quickEditStateService: accessor.get(IQuickEditStateService),
settingsStateService: accessor.get(IVoidSettingsService),
sidebarStateService: accessor.get(ISidebarStateService),
threadsStateService: accessor.get(IThreadHistoryService),
diff --git a/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts b/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts
index 5d6c0c49..e33c9991 100644
--- a/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts
+++ b/src/vs/workbench/contrib/void/browser/inlineDiffsService.ts
@@ -11,7 +11,7 @@ import { ICodeEditor, IOverlayWidget, IViewZone } from '../../../../editor/brows
// import { IUndoRedoService } from '../../../../platform/undoRedo/common/undoRedo.js';
import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
// import { throttle } from '../../../../base/common/decorators.js';
-import { writeFileWithDiffInstructions } from './prompt/systemPrompts.js';
+import { writeFileWithDiffInstructions } from './prompt/prompts.js';
import { ComputedDiff, findDiffs } from './helpers/findDiffs.js';
import { EndOfLinePreference, ITextModel } from '../../../../editor/common/model.js';
import { IRange } from '../../../../editor/common/core/range.js';
diff --git a/src/vs/workbench/contrib/void/browser/prompt/systemPrompts.ts b/src/vs/workbench/contrib/void/browser/prompt/prompts.ts
similarity index 88%
rename from src/vs/workbench/contrib/void/browser/prompt/systemPrompts.ts
rename to src/vs/workbench/contrib/void/browser/prompt/prompts.ts
index 161fd30b..803029c2 100644
--- a/src/vs/workbench/contrib/void/browser/prompt/systemPrompts.ts
+++ b/src/vs/workbench/contrib/void/browser/prompt/prompts.ts
@@ -3,38 +3,36 @@
* Void Editor additions licensed under the AGPL 3.0 License.
*--------------------------------------------------------------------------------------------*/
-// // used for ctrl+l
-// const partialGenerationInstructions = ``
+
+import { CodeSelection } from '../threadHistoryService.js';
+
+const stringifySelections = (selections: CodeSelection[]) => {
+
+ return selections.map(({ fileURI, content, selectionStr }) =>
+ `\
+File: ${fileURI.fsPath}
+\`\`\`
+${content // this was the enite file which is foolish
+ }
+\`\`\`${selectionStr === null ? '' : `
+Selection: ${selectionStr}`}
+`).join('\n')
+}
-// // used for ctrl+k, autocomplete
-// const fimInstructions = ``
+export const generateCtrlLPrompt = (instructions: string, selections: CodeSelection[] | null) => {
+ let str = '';
+ if (selections && selections.length > 0) {
+ str += stringifySelections(selections);
+ str += `Please edit the selected code following these instructions:\n`
+ }
+ str += `${instructions}`;
+ return str;
+};
-// CTRL+K prompt:
-// const promptContent = `Here is the user's original selection:
-// \`\`\`
-// ${selection}
-// \`\`\`
-// The user wants to apply the following instructions to the selection:
-// ${instructions}
-
-// Please rewrite the selection following the user's instructions.
-
-// Instructions to follow:
-// 1. Follow the user's instructions
-// 2. You may ONLY CHANGE the selection, and nothing else in the file
-// 3. Make sure all brackets in the new selection are balanced the same was as in the original selection
-// 3. Be careful not to duplicate or remove variables, comments, or other syntax by mistake
-
-// Complete the following:
-// \`\`\`
-//
${prefix}
-// ${suffix}
-// `;
-
-export const generateCtrlLInstructions = `\
+export const ctrlLSystem = `\
You are a coding assistant. You are given a list of relevant files \`files\`, a selection that the user is making \`selection\`, and instructions to follow \`instructions\`.
Please edit the selected file following the user's instructions (or, if appropriate, answer their question instead).
@@ -118,9 +116,33 @@ Memoization Object: A memo object is used to store the results of Fibonacci calc
Check Memo: Before computing fib(n), the function checks if the result is already in memo. If it is, it returns the stored result.
Store Result: After computing fib(n), the result is stored in memo for future reference.
-## END EXAMPLES
+## END EXAMPLES\
`
+export const generateCtrlKPrompt = ({ selection, prefix, suffix, instructions, }: { selection: string, prefix: string, suffix: string, instructions: string, }) => `\
+Here is the user's original selection:
+\`\`\`
+${selection}
+\`\`\`
+
+The user wants to apply the following instructions to the selection:
+${instructions}
+
+Please rewrite the selection following the user's instructions.
+
+Instructions to follow:
+1. Follow the user's instructions
+2. You may ONLY CHANGE the selection, and nothing else in the file
+3. Make sure all brackets in the new selection are balanced the same was as in the original selection
+3. Be careful not to duplicate or remove variables, comments, or other syntax by mistake
+
+Complete the following:
+\`\`\`
+${prefix}
+${suffix}
+`;
+
+
export const generateDiffInstructions = `
You are a coding assistant. You are given a list of relevant files \`files\`, a selection that the user is making \`selection\`, and instructions to follow \`instructions\`.
diff --git a/src/vs/workbench/contrib/void/browser/prompt/stringifySelections.ts b/src/vs/workbench/contrib/void/browser/prompt/stringifySelections.ts
deleted file mode 100644
index e23ac6f4..00000000
--- a/src/vs/workbench/contrib/void/browser/prompt/stringifySelections.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Glass Devtools, Inc. All rights reserved.
- * Void Editor additions licensed under the AGPL 3.0 License.
- *--------------------------------------------------------------------------------------------*/
-
-import { CodeSelection } from '../threadHistoryService.js';
-
-export const stringifySelections = (selections: CodeSelection[]) => {
-
-
-
- return selections.map(({ fileURI, content, selectionStr }) =>
- `\
-File: ${fileURI.fsPath}
-\`\`\`
-${content // this was the enite file which is foolish
- }
-\`\`\`${selectionStr === null ? '' : `
-Selection: ${selectionStr}`}
-`).join('\n')
-}
-
-
-export const userInstructionsStr = (instructions: string, selections: CodeSelection[] | null) => {
- let str = '';
- if (selections && selections.length > 0) {
- str += stringifySelections(selections);
- str += `Please edit the selected code following these instructions:\n`
- }
- str += `${instructions}`;
- return str;
-};
diff --git a/src/vs/workbench/contrib/void/browser/quickEditActions.ts b/src/vs/workbench/contrib/void/browser/quickEditActions.ts
index fcef7270..784011d2 100644
--- a/src/vs/workbench/contrib/void/browser/quickEditActions.ts
+++ b/src/vs/workbench/contrib/void/browser/quickEditActions.ts
@@ -1,9 +1,111 @@
import { KeyCode, KeyMod } from '../../../../base/common/keyCodes.js';
-import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
+import { ICodeEditor, IViewZone } from '../../../../editor/browser/editorBrowser.js';
import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js';
-import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
+import { createDecorator, IInstantiationService, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
import { IMetricsService } from '../../../../platform/void/common/metricsService.js';
+import { Emitter, Event } from '../../../../base/common/event.js';
+// import { IInlineDiffService } from '../../../../editor/browser/services/inlineDiffService/inlineDiffService.js';
+import { Disposable } from '../../../../base/common/lifecycle.js';
+import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
+import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
+import { mountCtrlK } from './react/out/ctrl-k-tsx/index.js';
+import { getReactServices } from './helpers/reactServicesHelper.js';
+import { URI } from '../../../../base/common/uri.js';
+
+
+type InitialZone = { uri: URI, startLine: number, selectedText: string, }
+
+export type QuickEditPropsType = {
+ quickEditId: number,
+}
+
+export type QuickEdit = {
+ startLine: number, // 0-indexed
+ beforeCode: string,
+ afterCode?: string,
+ instructions?: string,
+ responseText?: string, // model can produce a text response too
+}
+
+
+export interface IQuickEditService {
+ readonly _serviceBrand: undefined;
+ readonly onDidChangeState: Event;
+ addZone(zone: InitialZone): void;
+}
+
+export const IQuickEditService = createDecorator('voidQuickEditService');
+class VoidQuickEditService extends Disposable implements IQuickEditService {
+ _serviceBrand: undefined;
+
+ quickEditId: number = 0
+
+ private readonly _onDidChangeState = new Emitter();
+ readonly onDidChangeState: Event = this._onDidChangeState.event;
+
+ // state
+ // state: {}
+
+ constructor(
+ // @IInlineDiffService private readonly _inlineDiffService: IInlineDiffService,
+ @ICodeEditorService private readonly _editorService: ICodeEditorService,
+ @IInstantiationService private readonly _instantiationService: IInstantiationService,
+ ) {
+ super();
+ }
+
+ addZone(zone: InitialZone) {
+
+ const addZoneToEditor = (editor: ICodeEditor) => {
+
+ const model = editor.getModel()
+ if (!model) return
+
+ editor.changeViewZones(accessor => {
+
+ const domNode = document.createElement('div');
+ domNode.style.zIndex = '1'
+
+ // domNode.className = 'void-redBG'
+ const viewZone: IViewZone = {
+ // afterLineNumber: computedDiff.startLine - 1,
+ afterLineNumber: 1,
+ heightInPx: 100,
+ // heightInLines: 1,
+ // minWidthInPx: 200,
+ domNode: domNode,
+ // marginDomNode: document.createElement('div'), // displayed to left
+ suppressMouseDown: false,
+ };
+
+ // const zoneId =
+ accessor.addZone(viewZone)
+
+ this._instantiationService.invokeFunction(accessor => {
+ const services = getReactServices(accessor)
+
+ const props: QuickEditPropsType = {
+ quickEditId: this.quickEditId++,
+ }
+ mountCtrlK(domNode, services, props)
+ })
+
+ // disposeInThisEditorFns.push(() => { editor.changeViewZones(accessor => { if (zoneId) accessor.removeZone(zoneId) }) })
+ })
+ }
+
+
+ const editors = this._editorService.listCodeEditors().filter(editor => editor.getModel()?.uri.fsPath === zone.uri.fsPath)
+ for (const editor of editors) {
+ addZoneToEditor(editor)
+ }
+ }
+
+}
+
+registerSingleton(IQuickEditService, VoidQuickEditService, InstantiationType.Eager);
+
export const VOID_CTRL_K_ACTION_ID = 'void.ctrlKAction'
@@ -12,17 +114,25 @@ registerAction2(class extends Action2 {
super({ id: VOID_CTRL_K_ACTION_ID, title: 'Void: Quick Edit', keybinding: { primary: KeyMod.CtrlCmd | KeyCode.KeyK, weight: KeybindingWeight.BuiltinExtension } });
}
async run(accessor: ServicesAccessor): Promise {
- console.log('hello111!')
- const model = accessor.get(ICodeEditorService).getActiveCodeEditor()?.getModel()
- if (!model)
- return
-
- console.log('hello!')
+ const quickEditService = accessor.get(IQuickEditService)
+ const editorService = accessor.get(ICodeEditorService)
const metricsService = accessor.get(IMetricsService)
- metricsService.capture('User Action', { type: 'Ctrl+K' })
+ metricsService.capture('User Action', { type: 'Open Ctrl+K' })
+
+ const editor = editorService.getActiveCodeEditor()
+ if (!editor) return;
+ const model = editor.getModel()
+ if (!model) return;
+ const selection = editor.getSelection()
+ if (!selection) return;
+
+ const uri = model.uri
+ const startLine = selection.startLineNumber
+ const selectedText = model.getValueInRange(selection)
+
+ quickEditService.addZone({ uri, startLine, selectedText, })
- console.log('bye!')
}
});
diff --git a/src/vs/workbench/contrib/void/browser/quickEditStateService.ts b/src/vs/workbench/contrib/void/browser/quickEditStateService.ts
new file mode 100644
index 00000000..355b52f1
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/quickEditStateService.ts
@@ -0,0 +1,82 @@
+import { Emitter, Event } from '../../../../base/common/event.js';
+import { Disposable } from '../../../../base/common/lifecycle.js';
+import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
+import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js';
+import { QuickEdit } from './quickEditActions.js';
+
+
+
+// service that manages state
+export type VoidQuickEditState = {
+ quickEditsOfDocument: { [uri: string]: QuickEdit }
+}
+
+export interface IQuickEditStateService {
+ readonly _serviceBrand: undefined;
+
+ readonly state: VoidQuickEditState; // readonly to the user
+ setState(newState: Partial): void;
+ onDidChangeState: Event;
+
+ onDidFocusChat: Event;
+ onDidBlurChat: Event;
+ fireFocusChat(): void;
+ fireBlurChat(): void;
+
+}
+
+export const IQuickEditStateService = createDecorator('voidQuickEditStateService');
+class VoidQuickEditStateService extends Disposable implements IQuickEditStateService {
+ _serviceBrand: undefined;
+
+ static readonly ID = 'voidQuickEditStateService';
+
+ private readonly _onDidChangeState = new Emitter();
+ readonly onDidChangeState: Event = this._onDidChangeState.event;
+
+ private readonly _onFocusChat = new Emitter();
+ readonly onDidFocusChat: Event = this._onFocusChat.event;
+
+ private readonly _onBlurChat = new Emitter();
+ readonly onDidBlurChat: Event = this._onBlurChat.event;
+
+
+ // state
+ state: VoidQuickEditState
+
+ constructor(
+ // @IViewsService private readonly _viewsService: IViewsService,
+ ) {
+ super()
+
+ // initial state
+ this.state = { quickEditsOfDocument: {} }
+ }
+
+
+ setState(newState: Partial) {
+ // make sure view is open if the tab changes
+ // if ('currentTab' in newState) {
+ // this.addQuickEdit()
+ // }
+
+ this.state = { ...this.state, ...newState }
+ this._onDidChangeState.fire()
+ }
+
+ fireFocusChat() {
+ this._onFocusChat.fire()
+ }
+
+ fireBlurChat() {
+ this._onBlurChat.fire()
+ }
+
+ // addQuickEdit() {
+ // this._viewsService.openViewContainer(VOID_VIEW_CONTAINER_ID);
+ // this._viewsService.openView(VOID_VIEW_ID);
+ // }
+
+}
+
+registerSingleton(IQuickEditStateService, VoidQuickEditStateService, InstantiationType.Eager);
diff --git a/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/CtrlK.tsx b/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/CtrlK.tsx
new file mode 100644
index 00000000..e57acf4a
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/CtrlK.tsx
@@ -0,0 +1,18 @@
+import { useEffect, useState } from 'react'
+import { useIsDark, useSidebarState } from '../util/services.js'
+import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js'
+import { CtrlKChat } from './CtrlKChat.js'
+import { QuickEditPropsType } from '../../../quickEditActions.js'
+
+export const CtrlK = (props: QuickEditPropsType) => {
+
+ const isDark = useIsDark()
+
+ return
+
+
+
+
+
+
+}
diff --git a/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/CtrlKChat.tsx b/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/CtrlKChat.tsx
new file mode 100644
index 00000000..edfb3664
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/CtrlKChat.tsx
@@ -0,0 +1,83 @@
+
+import React, { FormEvent, useCallback, useRef, useState } from 'react';
+import { useSettingsState, useSidebarState, useThreadsState, useQuickEditState, useService } from '../util/services.js';
+import { OnError } from '../../../../../../../platform/void/common/llmMessageTypes.js';
+import { InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js';
+import { getCmdKey } from '../../../helpers/getCmdKey.js';
+import { VoidInputBox } from '../util/inputs.js';
+import { QuickEditPropsType } from '../../../quickEditActions.js';
+
+export const CtrlKChat = (props: QuickEditPropsType) => {
+
+ const inputBoxRef: React.MutableRefObject = useRef(null);
+
+ // -- imported state --
+ // const threadsStateService = useService('service')
+ // const sidebarState = useSidebarState()
+
+ const quickEditState = useQuickEditState()
+
+
+ // -- local state --
+ // state of chat
+ const [messageStream, setMessageStream] = useState(null)
+ const [isLoading, setIsLoading] = useState(false)
+ const latestRequestIdRef = useRef(null)
+ const [latestError, setLatestError] = useState[0] | null>(null)
+
+
+ // state of current message
+ const [instructions, setInstructions] = useState('') // the user's instructions
+ const onChangeText = useCallback((newStr: string) => { setInstructions(newStr) }, [setInstructions])
+ const isDisabled = !instructions.trim()
+
+ const onSubmit = useCallback((e: FormEvent) => {
+ // TODO
+ }, [])
+
+ return
+
+
+
+}
diff --git a/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/index.tsx b/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/index.tsx
new file mode 100644
index 00000000..3b4882d5
--- /dev/null
+++ b/src/vs/workbench/contrib/void/browser/react/src/ctrl-k-tsx/index.tsx
@@ -0,0 +1,8 @@
+
+import { mountFnGenerator } from '../util/mountFnGenerator.js'
+import { CtrlK } from './CtrlK.js'
+
+
+export const mountCtrlK = mountFnGenerator(CtrlK)
+
+
diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx
index 976af32b..78419e49 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx
@@ -3,12 +3,10 @@
* Void Editor additions licensed under the AGPL 3.0 License.
*--------------------------------------------------------------------------------------------*/
-import React, { FormEvent, Fragment, useCallback, useEffect, useRef, useState } from 'react';
+import React, { ButtonHTMLAttributes, FormEvent, FormHTMLAttributes, Fragment, useCallback, useEffect, useRef, useState } from 'react';
import { useSettingsState, useService, useSidebarState, useThreadsState } from '../util/services.js';
-import { generateCtrlLInstructions, generateDiffInstructions } from '../../../prompt/systemPrompts.js';
-import { userInstructionsStr } from '../../../prompt/stringifySelections.js';
import { ChatMessage, CodeSelection, CodeStagingSelection } from '../../../threadHistoryService.js';
import { BlockCode } from '../markdown/BlockCode.js';
@@ -23,6 +21,7 @@ import { getCmdKey } from '../../../helpers/getCmdKey.js'
import { HistoryInputBox, InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js';
import { VoidInputBox } from '../util/inputs.js';
import { ModelDropdown } from '../void-settings-tsx/ModelDropdown.js';
+import { ctrlLSystem, generateCtrlLPrompt } from '../../../prompt/prompts.js';
const IconX = ({ size, className = '' }: { size: number, className?: string }) => {
@@ -85,6 +84,33 @@ const IconSquare = ({ size, className = '' }: { size: number, className?: string
);
};
+type ButtonProps = ButtonHTMLAttributes
+export const ButtonSubmit = ({ className, disabled, ...props }: ButtonProps & Required>) => {
+ return
+
+
+}
+
+export const ButtonStop = ({ className, ...props }: ButtonHTMLAttributes) => {
+
+ return
+
+
+}
+
const ScrollToBottomContainer = ({ children, className, style }: { children: React.ReactNode, className?: string, style?: React.CSSProperties }) => {
const [isAtBottom, setIsAtBottom] = useState(true); // Start at bottom
@@ -277,6 +303,8 @@ export const SidebarChat = () => {
const threadsState = useThreadsState()
const threadsStateService = useService('threadsStateService')
+ const llmMessageService = useService('llmMessageService')
+
// ----- SIDEBAR CHAT state (local) -----
// state of chat
@@ -286,7 +314,6 @@ export const SidebarChat = () => {
const [latestError, setLatestError] = useState[0] | null>(null)
- const llmMessageService = useService('llmMessageService')
// state of current message
const [instructions, setInstructions] = useState('') // the user's instructions
@@ -325,11 +352,11 @@ export const SidebarChat = () => {
// add system message to chat history
- const systemPromptElt: ChatMessage = { role: 'system', content: generateCtrlLInstructions }
+ const systemPromptElt: ChatMessage = { role: 'system', content: ctrlLSystem }
threadsStateService.addMessageToCurrentThread(systemPromptElt)
// add user's message to chat history
- const userHistoryElt: ChatMessage = { role: 'user', content: userInstructionsStr(instructions, selections), displayContent: instructions, selections: selections }
+ const userHistoryElt: ChatMessage = { role: 'user', content: generateCtrlLPrompt(instructions, selections), displayContent: instructions, selections: selections }
threadsStateService.addMessageToCurrentThread(userHistoryElt)
const currentThread = threadsStateService.getCurrentThread(threadsStateService.state) // the the instant state right now, don't wait for the React state
@@ -474,14 +501,14 @@ export const SidebarChat = () => {
{/* middle row */}
`@@[&_textarea]:!void-${style}`) // apply styles to ancestor input and textarea elements
+ // .map(style => `@@[&_textarea]:!void-${style}`) // apply styles to ancestor textarea elements
// .join(' ') +
// ` outline-none`
// .split(' ')
- // .map(style => `@@[&_div.monaco-inputbox]:!void-${style}`) // apply styles to ancestor input and textarea elements
+ // .map(style => `@@[&_div.monaco-inputbox]:!void-${style}`)
// .join(' ');
`@@[&_textarea]:!void-bg-transparent @@[&_textarea]:!void-outline-none @@[&_textarea]:!void-text-vscode-input-fg @@[&_textarea]:!void-min-h-[81px] @@[&_textarea]:!void-max-h-[500px]@@[&_div.monaco-inputbox]:!void- @@[&_div.monaco-inputbox]:!void-outline-none`
}
@@ -508,27 +535,14 @@ export const SidebarChat = () => {
{/* submit / stop button */}
{isLoading ?
// stop button
-
-
-
+ />
:
// submit button (up arrow)
-
-
-
+ />
}
diff --git a/src/vs/workbench/contrib/void/browser/react/src/util/mountFnGenerator.tsx b/src/vs/workbench/contrib/void/browser/react/src/util/mountFnGenerator.tsx
index d67932dd..b674e7d5 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/util/mountFnGenerator.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/util/mountFnGenerator.tsx
@@ -8,8 +8,7 @@ import * as ReactDOM from 'react-dom/client'
import { _registerServices } from './services.js';
import { ReactServicesType } from '../../../helpers/reactServicesHelper.js';
-
-export const mountFnGenerator = (Component: (params: any) => React.ReactNode) => (rootElement: HTMLElement, services: ReactServicesType) => {
+export const mountFnGenerator = (Component: (params: any) => React.ReactNode) => (rootElement: HTMLElement, services: ReactServicesType, props?: any) => {
if (typeof document === 'undefined') {
console.error('index.tsx error: document was undefined')
return
@@ -19,7 +18,7 @@ export const mountFnGenerator = (Component: (params: any) => React.ReactNode) =>
const root = ReactDOM.createRoot(rootElement)
- root.render( ); // tailwind dark theme indicator
+ root.render( ); // tailwind dark theme indicator
return disposables
}
diff --git a/src/vs/workbench/contrib/void/browser/react/src/util/services.tsx b/src/vs/workbench/contrib/void/browser/react/src/util/services.tsx
index 250363ce..09053f28 100644
--- a/src/vs/workbench/contrib/void/browser/react/src/util/services.tsx
+++ b/src/vs/workbench/contrib/void/browser/react/src/util/services.tsx
@@ -12,6 +12,7 @@ import { ReactServicesType } from '../../../helpers/reactServicesHelper.js'
import { VoidSidebarState } from '../../../sidebarStateService.js'
import { VoidSettingsState } from '../../../../../../../platform/void/common/voidSettingsService.js'
import { ColorScheme } from '../../../../../../../platform/theme/common/theme.js'
+import { VoidQuickEditState } from '../../../quickEditStateService.js'
// normally to do this you'd use a useEffect that calls .onDidChangeState(), but useEffect mounts too late and misses initial state changes
@@ -20,6 +21,9 @@ let services: ReactServicesType
// even if React hasn't mounted yet, the variables are always updated to the latest state.
// React listens by adding a setState function to these listeners.
+let quickEditState: VoidQuickEditState
+const quickEditStateListeners: Set<(s: VoidQuickEditState) => void> = new Set()
+
let sidebarState: VoidSidebarState
const sidebarStateListeners: Set<(s: VoidSidebarState) => void> = new Set()
@@ -50,7 +54,15 @@ export const _registerServices = (services_: ReactServicesType) => {
wasCalled = true
services = services_
- const { sidebarStateService, settingsStateService, threadsStateService, refreshModelService, themeService } = services
+ const { sidebarStateService, quickEditStateService, settingsStateService, threadsStateService, refreshModelService, themeService, } = services
+
+ quickEditState = quickEditStateService.state
+ disposables.push(
+ quickEditStateService.onDidChangeState(() => {
+ quickEditState = quickEditStateService.state
+ quickEditStateListeners.forEach(l => l(quickEditState))
+ })
+ )
sidebarState = sidebarStateService.state
disposables.push(
@@ -106,6 +118,16 @@ export const useService = (serviceName: T):
// -- state of services --
+export const useQuickEditState = () => {
+ const [s, ss] = useState(quickEditState)
+ useEffect(() => {
+ ss(quickEditState)
+ quickEditStateListeners.add(ss)
+ return () => { quickEditStateListeners.delete(ss) }
+ }, [ss])
+ return s
+}
+
export const useSidebarState = () => {
const [s, ss] = useState(sidebarState)
useEffect(() => {
diff --git a/src/vs/workbench/contrib/void/browser/react/tsup.config.js b/src/vs/workbench/contrib/void/browser/react/tsup.config.js
index 5e0df9c0..b66bb97d 100644
--- a/src/vs/workbench/contrib/void/browser/react/tsup.config.js
+++ b/src/vs/workbench/contrib/void/browser/react/tsup.config.js
@@ -9,6 +9,7 @@ export default defineConfig({
entry: [
'./src2/sidebar-tsx/index.tsx',
'./src2/void-settings-tsx/index.tsx',
+ './src2/ctrl-k-tsx/index.tsx',
'./src2/diff/index.tsx',
],
outDir: './out',