diff --git a/src/vs/workbench/contrib/void/browser/actionIDs.ts b/src/vs/workbench/contrib/void/browser/actionIDs.ts index b237ecf8..5efe6b25 100644 --- a/src/vs/workbench/contrib/void/browser/actionIDs.ts +++ b/src/vs/workbench/contrib/void/browser/actionIDs.ts @@ -4,3 +4,7 @@ export const VOID_CTRL_L_ACTION_ID = 'void.ctrlLAction' export const VOID_CTRL_K_ACTION_ID = 'void.ctrlKAction' + +export const VOID_ACCEPT_DIFF_ACTION_ID = 'void.acceptDiff' + +export const VOID_REJECT_DIFF_ACTION_ID = 'void.rejectDiff' diff --git a/src/vs/workbench/contrib/void/browser/editCodeService.ts b/src/vs/workbench/contrib/void/browser/editCodeService.ts index c3c31f55..2cc7d942 100644 --- a/src/vs/workbench/contrib/void/browser/editCodeService.ts +++ b/src/vs/workbench/contrib/void/browser/editCodeService.ts @@ -25,6 +25,8 @@ import { URI } from '../../../../base/common/uri.js'; import { IConsistentEditorItemService, IConsistentItemService } from './helperServices/consistentItemService.js'; import { voidPrefixAndSuffix, ctrlKStream_userMessage, ctrlKStream_systemMessage, defaultQuickEditFimTags, rewriteCode_systemMessage, rewriteCode_userMessage, searchReplaceGivenDescription_systemMessage, searchReplaceGivenDescription_userMessage, tripleTick, } from '../common/prompt/prompts.js'; import { IVoidCommandBarService } from './voidCommandBarService.js'; +import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js'; +import { VOID_ACCEPT_DIFF_ACTION_ID, VOID_REJECT_DIFF_ACTION_ID } from './actionIDs.js'; import { mountCtrlK } from './react/out/quick-edit-tsx/index.js' import { QuickEditPropsType } from './quickEditActions.js'; @@ -2252,9 +2254,12 @@ registerSingleton(IEditCodeService, EditCodeService, InstantiationType.Eager); +const processRawKeybindingText = (keybindingStr: string) => { + return keybindingStr + .replace(/Enter/g, '↵') // ⏎ + .replace(/Backspace/g, '⌫') - - +} class AcceptRejectInlineWidget extends Widget implements IOverlayWidget { @@ -2282,7 +2287,8 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget { startLine: number, offsetLines: number }, - @IVoidCommandBarService private readonly _voidCommandBarService: IVoidCommandBarService + @IVoidCommandBarService private readonly _voidCommandBarService: IVoidCommandBarService, + @IKeybindingService private readonly _keybindingService: IKeybindingService ) { super(); @@ -2302,6 +2308,27 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget { const lineHeight = editor.getOption(EditorOption.lineHeight); + const getAcceptRejectText = () => { + const acceptKeybinding = this._keybindingService.lookupKeybinding(VOID_ACCEPT_DIFF_ACTION_ID); + const rejectKeybinding = this._keybindingService.lookupKeybinding(VOID_REJECT_DIFF_ACTION_ID); + + const acceptKeybindLabel = processRawKeybindingText(acceptKeybinding && acceptKeybinding.getLabel() || ''); + const rejectKeybindLabel = processRawKeybindingText(rejectKeybinding && rejectKeybinding.getLabel() || '') + + const commandBarStateAtUri = this._voidCommandBarService.stateOfURI[uri.fsPath]; + const selectedDiffIdx = commandBarStateAtUri?.diffIdx ?? 0; // 0th item is selected by default + const thisDiffIdx = commandBarStateAtUri?.sortedDiffIds.indexOf(diffid) ?? null; + + const showLabel = thisDiffIdx === selectedDiffIdx + + const acceptText = `Accept${showLabel ? ` ` + acceptKeybindLabel : ''}`; + const rejectText = `Reject${showLabel ? ` ` + rejectKeybindLabel : ''}`; + + return { acceptText, rejectText } + } + + const { acceptText, rejectText } = getAcceptRejectText() + // Create container div with buttons const { acceptButton, rejectButton, buttons } = dom.h('div@buttons', [ dom.h('button@acceptButton', []), @@ -2315,11 +2342,14 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget { buttons.style.paddingRight = '4px'; buttons.style.zIndex = '1'; buttons.style.transform = `translateY(${offsetLines * lineHeight}px)`; + buttons.style.justifyContent = 'flex-end'; + buttons.style.width = '100%'; + buttons.style.pointerEvents = 'none'; // Style accept button acceptButton.onclick = onAccept; - acceptButton.textContent = 'Accept'; + acceptButton.textContent = acceptText; acceptButton.style.backgroundColor = acceptBg; acceptButton.style.border = acceptBorder; acceptButton.style.color = buttonTextColor; @@ -2333,10 +2363,12 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget { acceptButton.style.cursor = 'pointer'; acceptButton.style.height = '100%'; acceptButton.style.boxShadow = '0 2px 3px rgba(0,0,0,0.2)'; + acceptButton.style.pointerEvents = 'auto'; + // Style reject button rejectButton.onclick = onReject; - rejectButton.textContent = 'Reject'; + rejectButton.textContent = rejectText; rejectButton.style.backgroundColor = rejectBg; rejectButton.style.border = rejectBorder; rejectButton.style.color = buttonTextColor; @@ -2350,6 +2382,7 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget { rejectButton.style.cursor = 'pointer'; rejectButton.style.height = '100%'; rejectButton.style.boxShadow = '0 2px 3px rgba(0,0,0,0.2)'; + rejectButton.style.pointerEvents = 'auto'; @@ -2384,18 +2417,12 @@ class AcceptRejectInlineWidget extends Widget implements IOverlayWidget { // Listen for state changes in the command bar service this._register(this._voidCommandBarService.onDidChangeState(e => { if (uri && e.uri.fsPath === uri.fsPath) { - const commandBarStateAtUri = this._voidCommandBarService.stateOfURI[uri.fsPath]; - const selectedDiffIdx = commandBarStateAtUri?.diffIdx ?? null; - const thisDiffIdx = commandBarStateAtUri?.sortedDiffIds.indexOf(diffid) ?? null; - // Update button text based on styles - if (thisDiffIdx !== null && selectedDiffIdx === thisDiffIdx) { - acceptButton.textContent = 'Accept'; - rejectButton.textContent = 'Reject'; - } else { - acceptButton.textContent = 'Accept'; - rejectButton.textContent = 'Reject'; - } + const { acceptText, rejectText } = getAcceptRejectText() + + acceptButton.textContent = acceptText; + rejectButton.textContent = rejectText; + } })); diff --git a/src/vs/workbench/contrib/void/browser/editCodeServiceInterface.ts b/src/vs/workbench/contrib/void/browser/editCodeServiceInterface.ts index 26ff9d2b..4d7fafd6 100644 --- a/src/vs/workbench/contrib/void/browser/editCodeServiceInterface.ts +++ b/src/vs/workbench/contrib/void/browser/editCodeServiceInterface.ts @@ -54,6 +54,8 @@ export interface IEditCodeService { diffOfId: Record; acceptOrRejectAllDiffAreas(opts: { uri: URI, removeCtrlKs: boolean, behavior: 'reject' | 'accept', _addToHistory?: boolean }): void; + acceptDiff({ diffid }: { diffid: number }): void; + rejectDiff({ diffid }: { diffid: number }): void; // events onDidAddOrDeleteDiffZones: Event<{ uri: URI }>; diff --git a/src/vs/workbench/contrib/void/browser/voidCommandBarService.ts b/src/vs/workbench/contrib/void/browser/voidCommandBarService.ts index e26bf5c9..63e66f69 100644 --- a/src/vs/workbench/contrib/void/browser/voidCommandBarService.ts +++ b/src/vs/workbench/contrib/void/browser/voidCommandBarService.ts @@ -18,6 +18,14 @@ import { IEditCodeService } from './editCodeServiceInterface.js'; import { ITextModel } from '../../../../editor/common/model.js'; import { IModelService } from '../../../../editor/common/services/model.js'; import { generateUuid } from '../../../../base/common/uuid.js'; +import { Action2, registerAction2 } from '../../../../platform/actions/common/actions.js'; +import { VOID_ACCEPT_DIFF_ACTION_ID, VOID_REJECT_DIFF_ACTION_ID } from './actionIDs.js'; +import { localize2 } from '../../../../nls.js'; +import { KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js'; +import { ServicesAccessor } from '../../../../editor/browser/editorExtensions.js'; +import { IMetricsService } from '../common/metricsService.js'; +import { KeyMod } from '../../../../editor/common/services/editorBaseApi.js'; +import { KeyCode } from '../../../../base/common/keyCodes.js'; @@ -456,3 +464,74 @@ class AcceptRejectAllFloatingWidget extends Widget implements IOverlayWidget { super.dispose(); } } + + +registerAction2(class extends Action2 { + constructor() { + super({ + id: VOID_ACCEPT_DIFF_ACTION_ID, + f1: true, + title: localize2('voidAcceptDiffAction', 'Void: Accept Diff'), + keybinding: { + primary: KeyMod.Alt | KeyMod.Shift | KeyCode.Enter, + weight: KeybindingWeight.VoidExtension, + } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editCodeService = accessor.get(IEditCodeService); + const commandBarService = accessor.get(IVoidCommandBarService); + const metricsService = accessor.get(IMetricsService); + + + const activeURI = commandBarService.activeURI; + if (!activeURI) return; + + const commandBarState = commandBarService.stateOfURI[activeURI.fsPath]; + if (!commandBarState) return; + const diffIdx = commandBarState.diffIdx ?? 0; + + const diffid = commandBarState.sortedDiffIds[diffIdx]; + if (!diffid) return; + + metricsService.capture('Accept Diff', { diffid, keyboard: true }); + editCodeService.acceptDiff({ diffid: parseInt(diffid) }) + + } +}); + + + +registerAction2(class extends Action2 { + constructor() { + super({ + id: VOID_REJECT_DIFF_ACTION_ID, + f1: true, + title: localize2('voidRejectDiffAction', 'Void: Reject Diff'), + keybinding: { + primary: KeyMod.Alt | KeyMod.Shift | KeyCode.Backspace, + weight: KeybindingWeight.VoidExtension, + } + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editCodeService = accessor.get(IEditCodeService); + const commandBarService = accessor.get(IVoidCommandBarService); + const metricsService = accessor.get(IMetricsService); + + const activeURI = commandBarService.activeURI; + if (!activeURI) return; + + const commandBarState = commandBarService.stateOfURI[activeURI.fsPath]; + if (!commandBarState) return; + const diffIdx = commandBarState.diffIdx ?? 0; + + const diffid = commandBarState.sortedDiffIds[diffIdx]; + if (!diffid) return; + + metricsService.capture('Reject Diff', { diffid, keyboard: true }); + editCodeService.rejectDiff({ diffid: parseInt(diffid) }) + } +});