Skip to content

Commit

Permalink
Merge Go To and Accept in gutter menu (#238446)
Browse files Browse the repository at this point in the history
  • Loading branch information
benibenj authored Jan 22, 2025
1 parent 63c3204 commit 70f22f5
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { ChildNode, FirstFnArg, LiveElement, n } from './utils.js';
export class GutterIndicatorMenuContent {
constructor(
private readonly _menuTitle: IObservable<string>,
private readonly _selectionOverride: IObservable<'jump' | 'accept' | undefined>,
private readonly _tabAction: IObservable<'jump' | 'accept' | 'inactive'>,
private readonly _close: (focusEditor: boolean) => void,
private readonly _extensionCommands: IObservable<readonly Command[] | undefined>,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
Expand All @@ -36,27 +36,25 @@ export class GutterIndicatorMenuContent {

private _createHoverContent() {
const activeElement = observableValue<string | undefined>('active', undefined);
const activeElementOrDefault = derived(reader => this._selectionOverride.read(reader) ?? activeElement.read(reader));

const createOptionArgs = (options: { id: string; title: string; icon: ThemeIcon; commandId: string; commandArgs?: unknown[] }): FirstFnArg<typeof option> => {
const createOptionArgs = (options: { id: string; title: string; icon: IObservable<ThemeIcon> | ThemeIcon; commandId: string | IObservable<string>; commandArgs?: unknown[] }): FirstFnArg<typeof option> => {
return {
title: options.title,
icon: options.icon,
keybinding: this._getKeybinding(options.commandArgs ? undefined : options.commandId),
isActive: activeElementOrDefault.map(v => v === options.id),
keybinding: typeof options.commandId === 'string' ? this._getKeybinding(options.commandArgs ? undefined : options.commandId) : derived(reader => typeof options.commandId === 'string' ? undefined : this._getKeybinding(options.commandArgs ? undefined : options.commandId.read(reader)).read(reader)),
isActive: activeElement.map(v => v === options.id),
onHoverChange: v => activeElement.set(v ? options.id : undefined, undefined),
onAction: () => {
this._close(true);
return this._commandService.executeCommand(options.commandId, ...(options.commandArgs ?? []));
return this._commandService.executeCommand(typeof options.commandId === 'string' ? options.commandId : options.commandId.get(), ...(options.commandArgs ?? []));
},
};
};

// TODO make this menu contributable!
return hoverContent([
header(this._menuTitle),
option(createOptionArgs({ id: 'jump', title: localize('goto', "Go To"), icon: Codicon.arrowRight, commandId: new JumpToNextInlineEdit().id })),
option(createOptionArgs({ id: 'accept', title: localize('accept', "Accept"), icon: Codicon.check, commandId: new AcceptInlineCompletion().id })),
option(createOptionArgs({ id: 'gotoAndAccept', title: `${localize('goto', "Go To")} / ${localize('accept', "Accept")}`, icon: this._tabAction.map(action => action === 'accept' ? Codicon.check : Codicon.arrowRight), commandId: this._tabAction.map(action => action === 'accept' ? new AcceptInlineCompletion().id : new JumpToNextInlineEdit().id) })),
option(createOptionArgs({ id: 'reject', title: localize('reject', "Reject"), icon: Codicon.close, commandId: new HideInlineCompletion().id })),
separator(),
this._extensionCommands?.map(c => c && c.length > 0 ? [
Expand Down Expand Up @@ -100,7 +98,7 @@ function header(title: string | IObservable<string>) {

function option(props: {
title: string;
icon: ThemeIcon;
icon: IObservable<ThemeIcon> | ThemeIcon;
keybinding: IObservable<ResolvedKeybinding | undefined>;
isActive?: IObservable<boolean>;
onHoverChange?: (isHovered: boolean) => void;
Expand All @@ -123,7 +121,7 @@ function option(props: {
fontSize: 16,
display: 'flex',
}
}, [renderIcon(props.icon)]),
}, [ThemeIcon.isThemeIcon(props.icon) ? renderIcon(props.icon) : props.icon.map(icon => renderIcon(icon))]),
n.elem('span', {}, [props.title]),
n.div({
style: { marginLeft: 'auto', opacity: '0.6' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,30 +157,9 @@ export class InlineEditsGutterIndicator extends Disposable {
return 'inactive' as const;
});

private readonly _onClickAction = derived(this, reader => {
if (this._layout.map(d => d && d.docked).read(reader)) {
return {
selectionOverride: 'accept' as const,
action: () => {
this._editorObs.editor.focus();
this._model.get()?.accept();
}
};
} else {
return {
selectionOverride: 'jump' as const,
action: () => {
this._editorObs.editor.focus();
this._model.get()?.jump();
}
};
}
});

private readonly _iconRef = n.ref<HTMLDivElement>();
private _hoverVisible: boolean = false;
private readonly _isHoveredOverIcon = observableValue(this, false);
private readonly _hoverSelectionOverride = derived(this, reader => this._isHoveredOverIcon.read(reader) ? this._onClickAction.read(reader).selectionOverride : undefined);

private _showHover(): void {
if (this._hoverVisible) {
Expand All @@ -200,7 +179,7 @@ export class InlineEditsGutterIndicator extends Disposable {
const content = disposableStore.add(this._instantiationService.createInstance(
GutterIndicatorMenuContent,
displayName,
this._hoverSelectionOverride,
this._tabAction,
(focusEditor) => {
if (focusEditor) {
this._editorObs.editor.focus();
Expand Down Expand Up @@ -232,7 +211,17 @@ export class InlineEditsGutterIndicator extends Disposable {

private readonly _indicator = n.div({
class: 'inline-edits-view-gutter-indicator',
onclick: () => this._onClickAction.get().action(),
onclick: () => {
const model = this._model.get();
if (!model) { return; }
const docked = this._layout.map(l => l && l.docked).get();
this._editorObs.editor.focus();
if (docked) {
model.accept();
} else {
model.jump();
}
},
tabIndex: 0,
style: {
position: 'absolute',
Expand Down

0 comments on commit 70f22f5

Please sign in to comment.