add codeBoxId, but now will change to uri

This commit is contained in:
Andrew Pareles 2025-02-21 23:31:06 -08:00
parent 64ac6d4a12
commit 1079893527
4 changed files with 149 additions and 75 deletions

View file

@ -128,13 +128,16 @@ export type StartApplyingOpts = {
from: 'QuickEdit';
type: 'rewrite';
diffareaid: number; // id of the CtrlK area (contains text selection)
chatCodeBoxId: string | null;
} | {
from: 'ClickApply';
type: 'searchReplace' | 'rewrite';
applyStr: string;
chatCodeBoxId: string | null;
}
export type AddCtrlKOpts = {
startLine: number,
endLine: number,
@ -197,12 +200,11 @@ type DiffZone = {
isStreaming: true;
streamRequestIdRef: { current: string | null };
line: number;
applyBoxId?: string;
codeBoxId: string | null;
} | {
isStreaming: false;
streamRequestIdRef?: undefined;
line?: undefined;
applyBoxId?: undefined;
};
editorId?: undefined;
linkedStreamingDiffZone?: undefined;
@ -260,10 +262,10 @@ export interface IEditCodeService {
interruptCtrlKStreaming(opts: { diffareaid: number }): void;
onDidChangeCtrlKZoneStreaming: Event<{ uri: URI; diffareaid: number }>;
// // DiffZone streaming state
// isApplyBoxIdStreaming(opts: { applyBoxId: string }): boolean;
// interruptApplyBoxId(opts: { applyBoxId: string }): void;
// onDidChangeApplyBoxIdStreaming: Event<{ applyBoxId: string }>;
// // DiffZone codeBoxId streaming state
isCodeBoxIdStreaming(opts: { codeBoxId: string }): boolean;
interruptCodeBoxId(opts: { codeBoxId: string }): void;
onDidChangeCodeBoxIdStreaming: Event<{ codeBoxId: string }>;
// testDiffs(): void;
}
@ -284,12 +286,14 @@ class EditCodeService extends Disposable implements IEditCodeService {
// only applies to diffZones
// streamingDiffZones: Set<number> = new Set()
private readonly _onDidChangeDiffZoneStreaming = new Emitter<{ uri: URI; diffareaid: number }>();
private readonly _onDidChangeCtrlKZoneStreaming = new Emitter<{ uri: URI; diffareaid: number }>();
private readonly _onDidAddOrDeleteDiffZone = new Emitter<{ uri: URI }>();
private readonly _onDidAddOrDeleteDiffZones = new Emitter<{ uri: URI }>();
onDidChangeDiffZoneStreaming = this._onDidChangeDiffZoneStreaming.event
private readonly _onDidChangeCtrlKZoneStreaming = new Emitter<{ uri: URI; diffareaid: number }>();
onDidChangeCtrlKZoneStreaming = this._onDidChangeCtrlKZoneStreaming.event
private readonly _onDidChangeCodeBoxIdStreaming = new Emitter<{ uri: URI; diffareaid: number; codeBoxId: string }>();
onDidChangeCodeBoxIdStreaming = this._onDidChangeCodeBoxIdStreaming.event
constructor(
// @IHistoryService private readonly _historyService: IHistoryService, // history service is the history of pressing alt left/right
@ICodeEditorService private readonly _editorService: ICodeEditorService,
@ -342,7 +346,17 @@ class EditCodeService extends Disposable implements IEditCodeService {
}
this._register(this._onDidChangeDiffZoneStreaming.event(({ uri: uri_ }) => { if (uri_.fsPath === model.uri.fsPath) updateAcceptRejectAllUI() }))
this._register(this._onDidAddOrDeleteDiffZone.event(({ uri: uri_ }) => { if (uri_.fsPath === model.uri.fsPath) updateAcceptRejectAllUI() }))
this._register(this._onDidAddOrDeleteDiffZones.event(({ uri: uri_ }) => { if (uri_.fsPath === model.uri.fsPath) updateAcceptRejectAllUI() }))
// codeBoxId
this._register(this._onDidChangeDiffZoneStreaming.event(({ diffareaid }) => {
const diffZone = this.diffAreaOfId[diffareaid]
if (diffZone?.type !== 'DiffZone') return
if (!diffZone._streamState.isStreaming) return
const { codeBoxId } = diffZone._streamState
if (codeBoxId === null) return
this._onDidChangeCodeBoxIdStreaming.fire({ uri: model.uri, codeBoxId, diffareaid })
}))
}
// initialize all existing models + initialize when a new model mounts
@ -864,7 +878,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
}
this.diffAreasOfURI[uri.fsPath].add(diffareaid)
}
this._onDidAddOrDeleteDiffZone.fire({ uri })
this._onDidAddOrDeleteDiffZones.fire({ uri })
// restore file content
const numLines = this._getNumLines(uri)
@ -934,7 +948,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
this._clearAllDiffAreaEffects(diffZone)
delete this.diffAreaOfId[diffZone.diffareaid]
this.diffAreasOfURI[diffZone._URI.fsPath].delete(diffZone.diffareaid.toString())
this._onDidAddOrDeleteDiffZone.fire({ uri: diffZone._URI })
this._onDidAddOrDeleteDiffZones.fire({ uri: diffZone._URI })
}
private _deleteTrackingZone(trackingZone: TrackingZone<unknown>) {
@ -1252,7 +1266,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
private _initializeWriteoverStream(opts: StartApplyingOpts): DiffZone | undefined {
const { from } = opts
const { from, chatCodeBoxId } = opts
let startLine: number
let endLine: number
@ -1312,13 +1326,14 @@ class EditCodeService extends Disposable implements IEditCodeService {
isStreaming: true,
streamRequestIdRef,
line: startLine,
codeBoxId: chatCodeBoxId,
},
_diffOfId: {}, // added later
_removeStylesFns: new Set(),
}
const diffZone = this._addDiffArea(adding)
this._onDidChangeDiffZoneStreaming.fire({ uri, diffareaid: diffZone.diffareaid })
this._onDidAddOrDeleteDiffZone.fire({ uri })
this._onDidAddOrDeleteDiffZones.fire({ uri })
if (from === 'QuickEdit') {
const { diffareaid } = opts
@ -1436,7 +1451,8 @@ class EditCodeService extends Disposable implements IEditCodeService {
private _initializeSearchAndReplaceStream({ applyStr }: { applyStr: string }) {
private _initializeSearchAndReplaceStream(opts: StartApplyingOpts & { from: 'ClickApply' }) {
const { applyStr, chatCodeBoxId } = opts
const uri_ = this._getActiveEditorURI()
if (!uri_) return
@ -1485,13 +1501,14 @@ class EditCodeService extends Disposable implements IEditCodeService {
isStreaming: true,
streamRequestIdRef,
line: startLine,
codeBoxId: chatCodeBoxId,
},
_diffOfId: {}, // added later
_removeStylesFns: new Set(),
}
const diffZone = this._addDiffArea(adding)
this._onDidChangeDiffZoneStreaming.fire({ uri, diffareaid: diffZone.diffareaid })
this._onDidAddOrDeleteDiffZone.fire({ uri })
this._onDidAddOrDeleteDiffZones.fire({ uri })
const revertAndContinueHistory = () => {
@ -1729,12 +1746,16 @@ class EditCodeService extends Disposable implements IEditCodeService {
isDiffZoneStreaming({ diffareaid }: { diffareaid: number }) {
_interruptDiffZoneStreaming({ diffareaid }: { diffareaid: number }) {
const diffZone = this.diffAreaOfId[diffareaid]
if (diffZone?.type !== 'DiffZone') return false
return diffZone._streamState.isStreaming
if (diffZone?.type !== 'DiffZone') return
if (!diffZone._streamState.isStreaming) return
this._stopIfStreaming(diffZone)
this._undoHistory(diffZone._URI)
}
isCtrlKZoneStreaming({ diffareaid }: { diffareaid: number }) {
const ctrlKZone = this.diffAreaOfId[diffareaid]
if (!ctrlKZone) return false
@ -1743,15 +1764,6 @@ class EditCodeService extends Disposable implements IEditCodeService {
}
interruptDiffZoneStreaming({ diffareaid }: { diffareaid: number }) {
const diffZone = this.diffAreaOfId[diffareaid]
if (diffZone?.type !== 'DiffZone') return
if (!diffZone._streamState.isStreaming) return
this._stopIfStreaming(diffZone)
this._undoHistory(diffZone._URI)
}
// diffareaid of the ctrlKZone (even though the stream state is dictated by the linked diffZone)
interruptCtrlKStreaming({ diffareaid }: { diffareaid: number }) {
const ctrlKZone = this.diffAreaOfId[diffareaid]
@ -1762,11 +1774,37 @@ class EditCodeService extends Disposable implements IEditCodeService {
if (!linkedStreamingDiffZone) return
if (linkedStreamingDiffZone.type !== 'DiffZone') return
this.interruptDiffZoneStreaming({ diffareaid: linkedStreamingDiffZone.diffareaid })
this._interruptDiffZoneStreaming({ diffareaid: linkedStreamingDiffZone.diffareaid })
}
isCodeBoxIdStreaming({ codeBoxId }: { codeBoxId: string }) {
// brute force is OK for now
for (const diffareaid in this.diffAreaOfId) {
const diffArea = this.diffAreaOfId[diffareaid]
if (!diffArea) continue
if (diffArea.type !== 'DiffZone') continue
if (!diffArea._streamState.isStreaming) continue
if (diffArea._streamState.codeBoxId === codeBoxId) return true
}
return false
}
interruptCodeBoxId({ codeBoxId }: { codeBoxId: string }) {
// brute force for now is OK
for (const diffareaid in this.diffAreaOfId) {
const diffArea = this.diffAreaOfId[diffareaid]
if (!diffArea) continue
if (diffArea.type !== 'DiffZone') continue
if (!diffArea._streamState.isStreaming) continue
if (diffArea._streamState.codeBoxId === codeBoxId) {
this._interruptDiffZoneStreaming({ diffareaid: diffArea.diffareaid })
return
}
}
}
// public removeDiffZone(diffZone: DiffZone, behavior: 'reject' | 'accept') {
// const uri = diffZone._URI

View file

@ -1,5 +1,5 @@
import { useState, useEffect, useCallback } from 'react'
import { useAccessor, useIsDiffZoneStreaming } from '../util/services.js'
import { useAccessor, useCodeBoxIdStreamingState, useSettingsState } from '../util/services.js'
import { useRefState } from '../util/helpers.js'
import { isFeatureNameDisabled } from '../../../../common/voidSettingsTypes.js'
@ -44,54 +44,35 @@ const CopyButton = ({ codeStr }: { codeStr: string }) => {
}
const useStreamStateRef = ({ codeBoxId }: { codeBoxId: string | null }) => {
const accessor = useAccessor()
const editCodeService = accessor.get('IEditCodeService')
const [isStreamingRef, setIsStreamingRef] = useRefState(editCodeService.isCodeBoxIdStreaming({ codeBoxId }))
useCodeBoxIdStreamingState(useCallback((codeBoxId2, isStreaming) => {
if (codeBoxId !== codeBoxId2) return
setIsStreamingRef(isStreaming)
}, [codeBoxId, setIsStreamingRef]))
return [isStreamingRef, setIsStreamingRef] as const
}
const ApplyButton = ({ codeStr, codeBoxId }: { codeStr: string, codeBoxId: string }) => {
const StopButton = ({ codeBoxId }: { codeBoxId: string }) => {
const accessor = useAccessor()
const editCodeService = accessor.get('IEditCodeService')
const metricsService = accessor.get('IMetricsService')
const settingsState = useSettingsState()
// const isStreaming = useIsDiffZoneStreaming(isDiffAreaStreaming)
const [isStreamingRef, _] = useStreamStateRef({ codeBoxId })
// const onSubmit = useCallback(() => {
// const uri = editCodeService.startApplying({
// from: 'ClickApply',
// type: 'searchReplace',
// applyStr: codeStr,
// })
// metricsService.capture('Apply Code', { length: codeStr.length }) // capture the length only
// if (isStreaming) return
// setCurrentlyStreamingDiffZone(id ?? null)
// }, [isStreaming, editCodeService])
// const onInterrupt = useCallback(() => {
// if (currStreamingDiffZoneRef.current === null) return
// editCodeService.interruptStreaming(currStreamingDiffZoneRef.current)
// setCurrentlyStreamingDiffZone(null)
// textAreaFnsRef.current?.enable()
// }, [isStreaming, editCodeService])
const isSingleLine = !codeStr.includes('\n')
return <button
// btn btn-secondary btn-sm border text-sm border-vscode-input-border rounded
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-1 text-void-fg-1 hover:brightness-110 border border-vscode-input-border rounded`}
// onClick={onApply}
onClick={onInterrupt}
>
Apply
</button>
@ -103,8 +84,57 @@ const ApplyButton = ({ codeStr, codeBoxId }: { codeStr: string, codeBoxId: strin
export const ApplyBlockHoverButtons = ({ codeStr, codeBoxId }: { codeStr: string, codeBoxId: string | null }) => {
const accessor = useAccessor()
const editCodeService = accessor.get('IEditCodeService')
const metricsService = accessor.get('IMetricsService')
const settingsState = useSettingsState()
const isDisabled = !!isFeatureNameDisabled('Apply', settingsState)
const [isStreamingRef, _] = useStreamStateRef({ codeBoxId })
const onSubmit = useCallback(() => {
if (isDisabled) return
if (isStreamingRef.current) return
editCodeService.startApplying({
from: 'ClickApply',
type: 'searchReplace',
applyStr: codeStr,
chatCodeBoxId: codeBoxId,
})
metricsService.capture('Apply Code', { length: codeStr.length }) // capture the length only
}, [isStreamingRef, editCodeService, codeBoxId, codeStr, metricsService])
const onInterrupt = useCallback(() => {
if (isStreamingRef.current) return
if (codeBoxId === null) return
editCodeService.interruptCodeBoxId({ codeBoxId, })
metricsService.capture('Stop Apply', {})
}, [isStreamingRef, editCodeService, codeBoxId, metricsService])
const isSingleLine = !codeStr.includes('\n')
const applyButton = <button
// btn btn-secondary btn-sm border text-sm border-vscode-input-border rounded
className={`${isSingleLine ? '' : 'px-1 py-0.5'} text-sm bg-void-bg-1 text-void-fg-1 hover:brightness-110 border border-vscode-input-border rounded`}
onClick={onSubmit}
>
Apply
</button>
return <>
<CopyButton codeStr={codeStr} />
{codeBoxId !== null && <ApplyButton codeBoxId={codeBoxId} codeStr={codeStr} />}
{!isStreamingRef.current && <CopyButton codeStr={codeStr} />}
{!isStreamingRef.current && codeBoxId !== null && <ApplyButton codeBoxId={codeBoxId} codeStr={codeStr} />}
{!isStreamingRef.current && <StopButton codeStr={codeStr} />}
</>
}

View file

@ -65,6 +65,7 @@ export const QuickEditChat = ({
from: 'QuickEdit',
type: 'rewrite',
diffareaid,
chatCodeBoxId: null,
})
}, [isStreamingRef, isDisabled, editCodeService, diffareaid])

View file

@ -76,9 +76,7 @@ let colorThemeState: ColorScheme
const colorThemeStateListeners: Set<(s: ColorScheme) => void> = new Set()
const ctrlKZoneStreamingStateListeners: Set<(diffareaid: number, s: boolean) => void> = new Set()
let diffZoneStreamingState: Record<string, boolean>
const diffZoneStreamingStateListeners: Set<(diffareaid: number, state: boolean) => void> = new Set()
const codeBoxIdStreamingStateListeners: Set<(codeBoxId: string, s: boolean) => void> = new Set()
@ -184,6 +182,12 @@ export const _registerServices = (accessor: ServicesAccessor) => {
ctrlKZoneStreamingStateListeners.forEach(l => l(diffareaid, isStreaming))
})
)
disposables.push(
editCodeService.onDidChangeCodeBoxIdStreaming(({ codeBoxId }) => {
const isStreaming = editCodeService.isCodeBoxIdStreaming({ codeBoxId })
codeBoxIdStreamingStateListeners.forEach(l => l(codeBoxId, isStreaming))
})
)
@ -351,7 +355,6 @@ export const useRefreshModelListener = (listener: (providerName: RefreshableProv
}, [listener, refreshModelProviderListeners])
}
export const useCtrlKZoneStreamingState = (listener: (diffareaid: number, s: boolean) => void) => {
useEffect(() => {
ctrlKZoneStreamingStateListeners.add(listener)
@ -359,16 +362,18 @@ export const useCtrlKZoneStreamingState = (listener: (diffareaid: number, s: boo
}, [listener, ctrlKZoneStreamingStateListeners])
}
export const useIsDiffZoneStreaming = (diffareaid: number) => {
return { current: true }
export const useCodeBoxIdStreamingState = (listener: (codeBoxId: string, s: boolean) => void) => {
useEffect(() => {
codeBoxIdStreamingStateListeners.add(listener)
return () => { codeBoxIdStreamingStateListeners.delete(listener) }
}, [listener, codeBoxIdStreamingStateListeners])
}
export const useIsDark = () => {
const [s, ss] = useState(colorThemeState)
useEffect(() => {