mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
ctrlK progress...
This commit is contained in:
parent
ef8bba00b9
commit
a9b2ff631d
5 changed files with 223 additions and 177 deletions
|
|
@ -33,6 +33,7 @@ import { IPosition } from '../../../../editor/common/core/position.js';
|
|||
|
||||
import { mountCtrlK } from '../browser/react/out/ctrl-k-tsx/index.js'
|
||||
import { QuickEditPropsType } from './quickEditActions.js';
|
||||
import { InputBox } from '../../../../base/browser/ui/inputbox/inputBox.js';
|
||||
|
||||
const configOfBG = (color: Color) => {
|
||||
return { dark: color, light: color, hcDark: color, hcLight: color, }
|
||||
|
|
@ -103,7 +104,10 @@ type CtrlKZone = {
|
|||
type: 'CtrlKZone';
|
||||
originalCode?: undefined;
|
||||
userText: string | null;
|
||||
_alreadyMounted: boolean;
|
||||
|
||||
_zoneAlreadyMounted: boolean; // we only want the input zone to mount once
|
||||
_inputBox: InputBox | null;
|
||||
|
||||
} & CommonZoneProps
|
||||
|
||||
|
||||
|
|
@ -157,7 +161,7 @@ export interface IInlineDiffsService {
|
|||
readonly _serviceBrand: undefined;
|
||||
startApplying(opts: StartApplyingOpts): number | undefined;
|
||||
interruptStreaming(diffareaid: number): void;
|
||||
addCtrlKZone(opts: AddCtrlKOpts): number;
|
||||
addCtrlKZone(opts: AddCtrlKOpts): number | undefined;
|
||||
}
|
||||
|
||||
export const IInlineDiffsService = createDecorator<IInlineDiffsService>('inlineDiffAreasService');
|
||||
|
|
@ -231,8 +235,6 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// highlight the region
|
||||
private _addLineDecoration = (model: ITextModel | null, startLine: number, endLine: number, className: string, options?: Partial<IModelDecorationOptions>) => {
|
||||
if (model === null) return
|
||||
|
|
@ -251,91 +253,94 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
}
|
||||
|
||||
|
||||
|
||||
private _addDiffAreaStylesToURI = (uri: URI) => {
|
||||
private _addDiffZoneStylesToURI = (uri: URI) => {
|
||||
const model = this._getModel(uri)
|
||||
|
||||
const fullFileText = this._readURI(uri) ?? ''
|
||||
|
||||
|
||||
for (const diffareaid of this.diffAreasOfURI[uri.fsPath]) {
|
||||
const diffArea = this.diffAreaOfId[diffareaid]
|
||||
console.log('DA start and end:', diffArea.startLine, diffArea.endLine)
|
||||
|
||||
if (diffArea.type === 'DiffZone') {
|
||||
// add sweep styles to the diffZone
|
||||
if (diffArea._streamState.isStreaming) {
|
||||
// sweepLine ... sweepLine
|
||||
const fn1 = this._addLineDecoration(model, diffArea._streamState.line, diffArea._streamState.line, 'void-sweepIdxBG')
|
||||
// sweepLine+1 ... endLine
|
||||
const fn2 = this._addLineDecoration(model, diffArea._streamState.line + 1, diffArea.endLine, 'void-sweepBG')
|
||||
diffArea._removeStylesFns.add(() => { fn1?.(); fn2?.(); })
|
||||
}
|
||||
if (diffArea.type !== 'DiffZone') continue
|
||||
// add sweep styles to the diffZone
|
||||
if (diffArea._streamState.isStreaming) {
|
||||
// sweepLine ... sweepLine
|
||||
const fn1 = this._addLineDecoration(model, diffArea._streamState.line, diffArea._streamState.line, 'void-sweepIdxBG')
|
||||
// sweepLine+1 ... endLine
|
||||
const fn2 = this._addLineDecoration(model, diffArea._streamState.line + 1, diffArea.endLine, 'void-sweepBG')
|
||||
diffArea._removeStylesFns.add(() => { fn1?.(); fn2?.(); })
|
||||
|
||||
const newDiffAreaCode = fullFileText.split('\n').slice((diffArea.startLine - 1), (diffArea.endLine - 1) + 1).join('\n')
|
||||
const computedDiffs = findDiffs(diffArea.originalCode, newDiffAreaCode)
|
||||
|
||||
for (let computedDiff of computedDiffs) {
|
||||
this._addDiff(computedDiff, diffArea)
|
||||
}
|
||||
|
||||
}
|
||||
// highlight the ctrlK zone
|
||||
if (diffArea.type === 'CtrlKZone') {
|
||||
if (diffArea._alreadyMounted) continue
|
||||
diffArea._alreadyMounted = true
|
||||
|
||||
const consistentZoneId = this._zoneStyleService.addConsistentItemToURI({
|
||||
uri,
|
||||
fn: (editor) => {
|
||||
const domNode = document.createElement('div');
|
||||
domNode.style.zIndex = '1'
|
||||
domNode.style.display = 'hidden' // start hidden until mount and get computed size
|
||||
|
||||
const viewZone: IViewZone = {
|
||||
afterLineNumber: diffArea.startLine - 1,
|
||||
domNode: domNode,
|
||||
suppressMouseDown: false,
|
||||
};
|
||||
|
||||
// mount zone
|
||||
let zoneId: string | null = null
|
||||
editor.changeViewZones(accessor => { zoneId = accessor.addZone(viewZone); })
|
||||
|
||||
|
||||
|
||||
// mount react
|
||||
this._instantiationService.invokeFunction(accessor => {
|
||||
const props: QuickEditPropsType = {
|
||||
diffareaid: diffArea.diffareaid,
|
||||
onChangeHeight(height) {
|
||||
if (height === undefined) return
|
||||
domNode.style.display = 'block'
|
||||
viewZone.heightInPx = height
|
||||
editor.changeViewZones(accessor => { if (zoneId) { accessor.layoutZone(zoneId) } })
|
||||
},
|
||||
onUserUpdateText(text) { diffArea.userText = text; },
|
||||
initText: diffArea.userText,
|
||||
}
|
||||
mountCtrlK(domNode, accessor, props)
|
||||
})
|
||||
|
||||
|
||||
return () => {
|
||||
editor.changeViewZones(accessor => { if (zoneId) accessor.removeZone(zoneId) });
|
||||
domNode.remove();
|
||||
}
|
||||
},
|
||||
})
|
||||
diffArea._removeStylesFns.add(() => this._zoneStyleService.removeConsistentItemFromURI(consistentZoneId));
|
||||
|
||||
const fn = this._addLineDecoration(model, diffArea.startLine, diffArea.endLine, 'void-highlightBG')
|
||||
diffArea._removeStylesFns.add(() => fn?.());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private _computeDiffsAndAddStylesToURI = (uri: URI) => {
|
||||
const fullFileText = this._readURI(uri) ?? ''
|
||||
|
||||
for (const diffareaid of this.diffAreasOfURI[uri.fsPath]) {
|
||||
const diffArea = this.diffAreaOfId[diffareaid]
|
||||
if (diffArea.type !== 'DiffZone') continue
|
||||
|
||||
const newDiffAreaCode = fullFileText.split('\n').slice((diffArea.startLine - 1), (diffArea.endLine - 1) + 1).join('\n')
|
||||
const computedDiffs = findDiffs(diffArea.originalCode, newDiffAreaCode)
|
||||
for (let computedDiff of computedDiffs) {
|
||||
this._addDiff(computedDiff, diffArea)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private _addCtrlKZoneInputStyles = (ctrlKZone: CtrlKZone) => {
|
||||
const { _URI: uri } = ctrlKZone
|
||||
const consistentZoneId = this._zoneStyleService.addConsistentItemToURI({
|
||||
uri,
|
||||
fn: (editor) => {
|
||||
const domNode = document.createElement('div');
|
||||
domNode.style.zIndex = '1'
|
||||
// domNode.style.display = 'hidden' // start hidden until mount and get computed size
|
||||
|
||||
const viewZone: IViewZone = {
|
||||
afterLineNumber: ctrlKZone.startLine - 1,
|
||||
domNode: domNode,
|
||||
suppressMouseDown: false,
|
||||
};
|
||||
|
||||
// mount zone
|
||||
let zoneId: string | null = null
|
||||
editor.changeViewZones(accessor => { zoneId = accessor.addZone(viewZone); })
|
||||
|
||||
// mount react
|
||||
this._instantiationService.invokeFunction(accessor => {
|
||||
const props: QuickEditPropsType = {
|
||||
diffareaid: ctrlKZone.diffareaid,
|
||||
onGetInputBox(inputBox) {
|
||||
ctrlKZone._inputBox = inputBox
|
||||
// __TODO__ not sure why this requries a timeout
|
||||
setTimeout(() => inputBox.focus(), 0)
|
||||
},
|
||||
onChangeHeight(height) {
|
||||
if (height === undefined) return
|
||||
// domNode.style.display = 'block'
|
||||
viewZone.heightInPx = height
|
||||
editor.changeViewZones(accessor => { if (zoneId) { accessor.layoutZone(zoneId) } })
|
||||
},
|
||||
onUserUpdateText(text) { ctrlKZone.userText = text; },
|
||||
initText: ctrlKZone.userText,
|
||||
}
|
||||
mountCtrlK(domNode, accessor, props)
|
||||
})
|
||||
|
||||
return () => {
|
||||
editor.changeViewZones(accessor => { if (zoneId) accessor.removeZone(zoneId) });
|
||||
domNode.remove();
|
||||
}
|
||||
},
|
||||
})
|
||||
ctrlKZone._removeStylesFns.add(() => this._zoneStyleService.removeConsistentItemFromURI(consistentZoneId));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private _addDiffStylesToURI = (uri: URI, diff: Diff) => {
|
||||
const { type, diffid } = diff
|
||||
|
||||
|
|
@ -515,7 +520,8 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
...snapshottedDiffArea as DiffAreaSnapshot<CtrlKZone>,
|
||||
_URI: uri,
|
||||
_removeStylesFns: new Set(),
|
||||
_alreadyMounted: false,
|
||||
_zoneAlreadyMounted: false,
|
||||
_inputBox: null,
|
||||
}
|
||||
}
|
||||
this.diffAreasOfURI[uri.fsPath].add(diffareaid)
|
||||
|
|
@ -609,9 +615,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
private _diffidPool = 0 // each diff has an id
|
||||
private _addDiff(computedDiff: ComputedDiff, diffZone: DiffZone): Diff {
|
||||
|
||||
const uri = diffZone._URI
|
||||
|
||||
const diffid = this._diffidPool++
|
||||
|
||||
// create a Diff of it
|
||||
|
|
@ -698,75 +702,95 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
|
||||
private _refreshStylesAndDiffsInURI(uri: URI) {
|
||||
const content = this._readURI(uri)
|
||||
if (content === null) return
|
||||
|
||||
// 1. clear Diffs and DiffZone styles
|
||||
// 1. clear DiffZone styles and Diffs
|
||||
this._clearAllDiffZoneEffects(uri)
|
||||
|
||||
// 2. recompute all Diffs on each editor with this URI
|
||||
this._addDiffAreaStylesToURI(uri)
|
||||
// 2. style DiffZones (sweep, etc)
|
||||
this._addDiffZoneStylesToURI(uri)
|
||||
|
||||
// 3. add Diffs
|
||||
this._computeDiffsAndAddStylesToURI(uri)
|
||||
|
||||
// 4. style ctrl+K (add input zone and highlighting - only do this once)
|
||||
for (const diffareaid of this.diffAreasOfURI[uri.fsPath]) {
|
||||
const diffArea = this.diffAreaOfId[diffareaid]
|
||||
if (diffArea.type !== 'CtrlKZone') continue
|
||||
|
||||
const ctrlKZone: CtrlKZone = diffArea
|
||||
const { _zoneAlreadyMounted: _alreadyMounted } = ctrlKZone
|
||||
if (_alreadyMounted) continue
|
||||
ctrlKZone._zoneAlreadyMounted = true
|
||||
|
||||
// add zone for input
|
||||
this._addCtrlKZoneInputStyles(ctrlKZone)
|
||||
|
||||
// highlight
|
||||
const model = this._getModel(uri)
|
||||
const fn = this._addLineDecoration(model, ctrlKZone.startLine, ctrlKZone.endLine, 'void-highlightBG')
|
||||
ctrlKZone._removeStylesFns.add(() => fn?.());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @throttle(100)
|
||||
private _writeDiffZoneLLMText(diffArea: DiffArea, llmText: string, latestCurrentFileEnd: IPosition, newPosition: IPosition) {
|
||||
|
||||
if (diffArea.type !== 'DiffZone') return
|
||||
|
||||
// @throttle(100)
|
||||
private _writeDiffZoneLLMText(diffZone: DiffZone, llmText: string, latestCurrentFileEnd: IPosition, newPosition: IPosition) {
|
||||
|
||||
// ----------- 1. Write the new code to the document -----------
|
||||
// figure out where to highlight based on where the AI is in the stream right now, use the last diff to figure that out
|
||||
const uri = diffArea._URI
|
||||
const computedDiffs = findDiffs(diffArea.originalCode, llmText)
|
||||
const uri = diffZone._URI
|
||||
const computedDiffs = findDiffs(diffZone.originalCode, llmText)
|
||||
|
||||
// if not streaming, just write the new code
|
||||
if (!diffArea._streamState.isStreaming) {
|
||||
if (!diffZone._streamState.isStreaming) {
|
||||
this._writeText(uri, llmText,
|
||||
{ startLineNumber: diffArea.startLine, startColumn: 1, endLineNumber: diffArea.endLine, endColumn: Number.MAX_SAFE_INTEGER, } // 1-indexed
|
||||
{ startLineNumber: diffZone.startLine, startColumn: 1, endLineNumber: diffZone.endLine, endColumn: Number.MAX_SAFE_INTEGER, } // 1-indexed
|
||||
)
|
||||
}
|
||||
// if streaming, use diffs to figure out where to write new code
|
||||
else {
|
||||
// these are two different coordinate systems - new and old line number
|
||||
let newFileEndLine: number // get new[0...newStoppingPoint] with line=newStoppingPoint highlighted
|
||||
let oldFileStartLine: number // get original[oldStartingPoint...]
|
||||
let originalCodeStartLine: number // get original[oldStartingPoint...]
|
||||
|
||||
const lastDiff = computedDiffs.pop()
|
||||
|
||||
if (!lastDiff) {
|
||||
// if the writing is identical so far, display no changes
|
||||
newFileEndLine = 1
|
||||
oldFileStartLine = 1
|
||||
newFileEndLine = diffZone.startLine
|
||||
originalCodeStartLine = 1
|
||||
}
|
||||
else {
|
||||
if (lastDiff.type === 'insertion') {
|
||||
newFileEndLine = lastDiff.endLine
|
||||
oldFileStartLine = lastDiff.originalStartLine
|
||||
originalCodeStartLine = lastDiff.originalStartLine
|
||||
}
|
||||
else if (lastDiff.type === 'deletion') {
|
||||
newFileEndLine = lastDiff.startLine
|
||||
oldFileStartLine = lastDiff.originalStartLine
|
||||
originalCodeStartLine = lastDiff.originalStartLine
|
||||
}
|
||||
else if (lastDiff.type === 'edit') {
|
||||
newFileEndLine = lastDiff.endLine
|
||||
oldFileStartLine = lastDiff.originalStartLine
|
||||
originalCodeStartLine = lastDiff.originalStartLine
|
||||
}
|
||||
else {
|
||||
throw new Error(`Void: diff.type not recognized on: ${lastDiff}`)
|
||||
}
|
||||
}
|
||||
|
||||
diffArea._streamState.line = newFileEndLine
|
||||
diffZone._streamState.line = newFileEndLine
|
||||
|
||||
// lines are 1-indexed
|
||||
const newFileTop = llmText.split('\n').slice(0, (newFileEndLine - 1)).join('\n')
|
||||
const oldFileBottom = diffArea.originalCode.split('\n').slice((oldFileStartLine - 1), Infinity).join('\n')
|
||||
const newFileTop = llmText.split('\n').slice(diffZone.startLine, (newFileEndLine - 1)).join('\n')
|
||||
const oldFileBottom = diffZone.originalCode.split('\n').slice((originalCodeStartLine - 1), Infinity).join('\n')
|
||||
|
||||
const newCode = `${newFileTop}\n${oldFileBottom}`
|
||||
|
||||
this._writeText(uri, newCode,
|
||||
{ startLineNumber: diffArea.startLine, startColumn: 1, endLineNumber: diffArea.endLine, endColumn: Number.MAX_SAFE_INTEGER, } // 1-indexed
|
||||
{ startLineNumber: diffZone.startLine, startColumn: 1, endLineNumber: diffZone.endLine, endColumn: Number.MAX_SAFE_INTEGER, } // 1-indexed
|
||||
)
|
||||
|
||||
}
|
||||
|
|
@ -777,7 +801,58 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
|
||||
|
||||
|
||||
private _initializeApplyStream(opts: StartApplyingOpts): DiffZone | undefined {
|
||||
|
||||
|
||||
|
||||
// called first, then call startApplying
|
||||
public addCtrlKZone({ startLine, endLine, uri }: AddCtrlKOpts) {
|
||||
|
||||
// check if there's overlap with any other ctrlKZones and if so, focus them
|
||||
for (const diffareaid of this.diffAreasOfURI[uri.fsPath]) {
|
||||
const diffArea = this.diffAreaOfId[diffareaid]
|
||||
if (!diffArea) continue
|
||||
if (diffArea.type !== 'CtrlKZone') continue
|
||||
const noOverlap = diffArea.startLine > endLine || diffArea.endLine < startLine
|
||||
if (!noOverlap) {
|
||||
diffArea._inputBox?.focus()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const { onFinishEdit } = this._addToHistory(uri)
|
||||
|
||||
const adding: Omit<CtrlKZone, 'diffareaid'> = {
|
||||
type: 'CtrlKZone',
|
||||
startLine: startLine,
|
||||
endLine: endLine,
|
||||
_zoneAlreadyMounted: false,
|
||||
_URI: uri,
|
||||
userText: null,
|
||||
_removeStylesFns: new Set(),
|
||||
_inputBox: null,
|
||||
}
|
||||
const ctrlKZone = this._addDiffArea(adding)
|
||||
|
||||
this._refreshStylesAndDiffsInURI(uri)
|
||||
|
||||
|
||||
onFinishEdit()
|
||||
return ctrlKZone.diffareaid
|
||||
}
|
||||
|
||||
|
||||
|
||||
public startApplying(opts: StartApplyingOpts) {
|
||||
const addedDiffZone = this._initializeStartApplying(opts)
|
||||
return addedDiffZone?.diffareaid
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private _initializeStartApplying(opts: StartApplyingOpts): DiffZone | undefined {
|
||||
|
||||
const { featureName } = opts
|
||||
|
||||
|
|
@ -793,7 +868,6 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
uri = uri_
|
||||
|
||||
// __TODO__ reject all diffs in the diff area
|
||||
// __TODO__ deselect user's cursor
|
||||
|
||||
// in ctrl+L the start and end lines are the full document
|
||||
const numLines = this._getNumLines(uri)
|
||||
|
|
@ -816,30 +890,17 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
userMessage = opts.userMessage
|
||||
}
|
||||
else if (featureName === 'Ctrl+K') {
|
||||
console.log('INIT APPLY STREAM CTRLK')
|
||||
|
||||
const { diffareaid } = opts
|
||||
|
||||
const ctrlKZone = this.diffAreaOfId[diffareaid]
|
||||
if (ctrlKZone.type !== 'CtrlKZone') return
|
||||
|
||||
const { startLine: startLine_, endLine: endLine_, _URI, userText } = ctrlKZone
|
||||
uri = _URI
|
||||
|
||||
startLine = startLine_
|
||||
endLine = endLine_
|
||||
|
||||
// check if there's overlap with any other ctrlKZones and if so, focus them
|
||||
for (const diffareaid2 of this.diffAreasOfURI[uri.fsPath]) {
|
||||
if (diffareaid.toString() === diffareaid2) continue
|
||||
const da2 = this.diffAreaOfId[diffareaid2]
|
||||
if (!da2) continue
|
||||
const noOverlap = da2.startLine > endLine || da2.endLine < startLine
|
||||
if (!noOverlap) {
|
||||
// __TODO__ focus it
|
||||
return
|
||||
}
|
||||
}
|
||||
console.log('userTEXT', userText)
|
||||
|
||||
if (!userText) return
|
||||
userMessage = userText
|
||||
}
|
||||
|
|
@ -860,15 +921,12 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
const { onFinishEdit } = this._addToHistory(uri)
|
||||
|
||||
|
||||
// for Ctrl+K, delete the current ctrlKZone, swapping it out for a diffZone
|
||||
if (featureName === 'Ctrl+K') {
|
||||
const { diffareaid } = opts
|
||||
const ctrlKZone = this.diffAreaOfId[diffareaid]
|
||||
this._deleteDiffArea(ctrlKZone)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// // for Ctrl+K, delete the current ctrlKZone, swapping it out for a diffZone
|
||||
// if (featureName === 'Ctrl+K') {
|
||||
// const { diffareaid } = opts
|
||||
// const ctrlKZone = this.diffAreaOfId[diffareaid]
|
||||
// this._deleteDiffArea(ctrlKZone)
|
||||
// }
|
||||
|
||||
const adding: Omit<DiffZone, 'diffareaid'> = {
|
||||
type: 'DiffZone',
|
||||
|
|
@ -879,7 +937,7 @@ class InlineDiffsService extends Disposable implements IInlineDiffsService {
|
|||
_streamState: {
|
||||
isStreaming: true,
|
||||
streamRequestIdRef,
|
||||
line: 1,
|
||||
line: startLine,
|
||||
},
|
||||
_diffOfId: {}, // added later
|
||||
_removeStylesFns: new Set(),
|
||||
|
|
@ -952,35 +1010,6 @@ ${userMessage}
|
|||
|
||||
|
||||
|
||||
public addCtrlKZone({ startLine, endLine, uri }: AddCtrlKOpts) {
|
||||
|
||||
const { onFinishEdit } = this._addToHistory(uri)
|
||||
|
||||
const adding: Omit<CtrlKZone, 'diffareaid'> = {
|
||||
type: 'CtrlKZone',
|
||||
startLine: startLine,
|
||||
endLine: endLine,
|
||||
_alreadyMounted: false,
|
||||
_URI: uri,
|
||||
userText: null,
|
||||
_removeStylesFns: new Set(),
|
||||
}
|
||||
const ctrlKZone = this._addDiffArea(adding)
|
||||
|
||||
this._refreshStylesAndDiffsInURI(uri)
|
||||
|
||||
onFinishEdit()
|
||||
return ctrlKZone.diffareaid
|
||||
}
|
||||
|
||||
|
||||
|
||||
public startApplying(opts: StartApplyingOpts) {
|
||||
const addedDiffZone = this._initializeApplyStream(opts)
|
||||
return addedDiffZone?.diffareaid
|
||||
}
|
||||
|
||||
|
||||
private _stopIfStreaming(diffZone: DiffZone) {
|
||||
|
||||
const streamRequestId = diffZone._streamState.streamRequestIdRef?.current
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@ import { KeybindingWeight } from '../../../../platform/keybinding/common/keybind
|
|||
import { IMetricsService } from '../../../../platform/void/common/metricsService.js';
|
||||
import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
|
||||
import { IInlineDiffsService } from './inlineDiffsService.js';
|
||||
import { InputBox } from '../../../../base/browser/ui/inputbox/inputBox.js';
|
||||
|
||||
|
||||
export type QuickEditPropsType = {
|
||||
diffareaid: number,
|
||||
onGetInputBox: (i: InputBox) => void;
|
||||
onChangeHeight: (height: number) => void;
|
||||
onUserUpdateText: (text: string) => void;
|
||||
initText: string | null;
|
||||
|
|
@ -54,6 +56,9 @@ registerAction2(class extends Action2 {
|
|||
const { startLineNumber: startLine, endLineNumber: endLine } = selection
|
||||
const uri = model.uri
|
||||
|
||||
// deselect - clear selection
|
||||
editor.setSelection({ startLineNumber: startLine, endLineNumber: startLine, startColumn: 1, endColumn: 1 })
|
||||
|
||||
const inlineDiffsService = accessor.get(IInlineDiffsService)
|
||||
inlineDiffsService.addCtrlKZone({ startLine, endLine, uri })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,11 @@ import { VoidInputBox } from '../util/inputs.js';
|
|||
import { QuickEditPropsType } from '../../../quickEditActions.js';
|
||||
import { ButtonStop, ButtonSubmit } from '../sidebar-tsx/SidebarChat.js';
|
||||
|
||||
export const CtrlKChat = ({ diffareaid, onUserUpdateText, onChangeHeight, initText }: QuickEditPropsType) => {
|
||||
export const CtrlKChat = ({ diffareaid, onGetInputBox, onUserUpdateText, onChangeHeight, initText }: QuickEditPropsType) => {
|
||||
|
||||
const accessor = useAccessor()
|
||||
|
||||
const inlineDiffsService = accessor.get('IInlineDiffsService')
|
||||
|
||||
const sizerRef = useRef<HTMLDivElement | null>(null)
|
||||
|
||||
const inputBoxRef: React.MutableRefObject<InputBox | null> = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -24,13 +21,16 @@ export const CtrlKChat = ({ diffareaid, onUserUpdateText, onChangeHeight, initTe
|
|||
if (!inputContainer) return;
|
||||
|
||||
// only observing 1 element
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
let resizeObserver: ResizeObserver | undefined
|
||||
|
||||
resizeObserver = new ResizeObserver((entries) => {
|
||||
const height = entries[0].borderBoxSize[0].blockSize
|
||||
console.log('NEW HEIGHT', height)
|
||||
onChangeHeight(height)
|
||||
});
|
||||
})
|
||||
resizeObserver.observe(inputContainer);
|
||||
return () => { resizeObserver.disconnect(); };
|
||||
|
||||
return () => { resizeObserver?.disconnect(); };
|
||||
}, [onChangeHeight]);
|
||||
|
||||
// state of current message
|
||||
|
|
@ -46,6 +46,8 @@ export const CtrlKChat = ({ diffareaid, onUserUpdateText, onChangeHeight, initTe
|
|||
|
||||
const onSubmit = useCallback((e: FormEvent) => {
|
||||
if (currentlyStreamingIdRef.current !== undefined) return
|
||||
inputBoxRef.current?.disable()
|
||||
|
||||
currentlyStreamingIdRef.current = inlineDiffsService.startApplying({
|
||||
featureName: 'Ctrl+K',
|
||||
diffareaid: diffareaid,
|
||||
|
|
@ -70,11 +72,11 @@ export const CtrlKChat = ({ diffareaid, onUserUpdateText, onChangeHeight, initTe
|
|||
inputBoxRef.current.value = instructions
|
||||
}, [initText, instructions])
|
||||
|
||||
return <div className='py-2' ref={sizerRef}>
|
||||
return <div className='py-2 w-full max-w-xl' ref={sizerRef}>
|
||||
<form
|
||||
className={
|
||||
// copied from SidebarChat.tsx
|
||||
`flex flex-col gap-2 p-1 relative input text-left shrink-0
|
||||
// copied from SidebarChat.tsx
|
||||
className={`
|
||||
flex flex-col gap-2 p-1 relative input text-left shrink-0
|
||||
transition-all duration-200
|
||||
rounded-md
|
||||
bg-vscode-input-bg
|
||||
|
|
@ -103,7 +105,7 @@ export const CtrlKChat = ({ diffareaid, onUserUpdateText, onChangeHeight, initTe
|
|||
>
|
||||
|
||||
<div // this div is used to position the input box properly
|
||||
className={`right-0 left-0 m-2 z-[999]`}
|
||||
className={`w-full m-2 z-[999]`}
|
||||
>
|
||||
<div className='flex flex-row justify-between items-end gap-1'>
|
||||
{/* left (input) */}
|
||||
|
|
@ -114,13 +116,17 @@ export const CtrlKChat = ({ diffareaid, onUserUpdateText, onChangeHeight, initTe
|
|||
<VoidInputBox
|
||||
placeholder={`${getCmdKey()}+K to select`}
|
||||
onChangeText={onChangeText}
|
||||
inputBoxRef={inputBoxRef}
|
||||
onCreateInstance={useCallback((instance: InputBox) => {
|
||||
inputBoxRef.current = instance;
|
||||
onGetInputBox(instance);
|
||||
instance.focus()
|
||||
}, [onGetInputBox])}
|
||||
multiline={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* right (button) */}
|
||||
<div className='flex flex-row items-end'>
|
||||
<div className='flex flex-row items-end w-10'>
|
||||
{/* submit / stop button */}
|
||||
{isStreaming ?
|
||||
// stop button
|
||||
|
|
|
|||
|
|
@ -48,7 +48,10 @@ const CodeButtonsOnHover = ({ diffRepr: text }: { diffRepr: string }) => {
|
|||
<button
|
||||
className="btn btn-secondary btn-sm border border-vscode-input-border rounded"
|
||||
onClick={() => {
|
||||
inlineDiffService.startApplying({ featureName: 'Ctrl+L', userMessage: text })
|
||||
inlineDiffService.startApplying({
|
||||
featureName: 'Ctrl+L',
|
||||
userMessage: text,
|
||||
})
|
||||
}}
|
||||
>
|
||||
Apply
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js
|
|||
import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js';
|
||||
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { CodeStagingSelection, IThreadHistoryService } from './threadHistoryService.js';
|
||||
// import { IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
|
||||
import { IEditorService } from '../../../services/editor/common/editorService.js';
|
||||
import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';
|
||||
import { IRange } from '../../../../editor/common/core/range.js';
|
||||
import { ITextModel } from '../../../../editor/common/model.js';
|
||||
|
|
@ -66,18 +64,23 @@ registerAction2(class extends Action2 {
|
|||
|
||||
const stateService = accessor.get(ISidebarStateService)
|
||||
const metricsService = accessor.get(IMetricsService)
|
||||
const editorService = accessor.get(ICodeEditorService)
|
||||
|
||||
metricsService.capture('User Action', { type: 'Ctrl+L' })
|
||||
|
||||
stateService.setState({ isHistoryOpen: false, currentTab: 'chat' })
|
||||
stateService.fireFocusChat()
|
||||
|
||||
const editor = editorService.getActiveCodeEditor()
|
||||
const selectionRange = roundRangeToLines(
|
||||
accessor.get(IEditorService).activeTextEditorControl?.getSelection()
|
||||
// accessor.get(IEditorService).activeTextEditorControl?.getSelection()
|
||||
editor?.getSelection()
|
||||
)
|
||||
|
||||
|
||||
if (selectionRange) {
|
||||
// select whole lines
|
||||
editor?.setSelection({ startLineNumber: selectionRange.startLineNumber, endLineNumber: selectionRange.endLineNumber, startColumn: 1, endColumn: Number.MAX_SAFE_INTEGER })
|
||||
|
||||
const selectionStr = getContentInRange(model, selectionRange)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue