@sussudio/platform
Version:
Internal APIs for VS Code's service injection the base services.
290 lines (289 loc) • 9.68 kB
JavaScript
var __decorate =
(this && this.__decorate) ||
function (decorators, target, key, desc) {
var c = arguments.length,
r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc,
d;
if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param =
(this && this.__param) ||
function (paramIndex, decorator) {
return function (target, key) {
decorator(target, key, paramIndex);
};
};
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from '@sussudio/base/browser/dom.mjs';
import { ActionBar } from '@sussudio/base/browser/ui/actionbar/actionbar.mjs';
import { Disposable, DisposableStore, MutableDisposable } from '@sussudio/base/common/lifecycle.mjs';
import '../../../css!./actionWidget.mjs';
import { localize } from 'vscode-nls.mjs';
import { Action2, registerAction2 } from '../../actions/common/actions.mjs';
import { acceptSelectedActionCommand, ActionList, previewSelectedActionCommand } from './actionList.mjs';
import { IContextKeyService, RawContextKey } from '../../contextkey/common/contextkey.mjs';
import { IContextViewService } from '../../contextview/browser/contextView.mjs';
import { registerSingleton } from '../../instantiation/common/extensions.mjs';
import { createDecorator, IInstantiationService } from '../../instantiation/common/instantiation.mjs';
const ActionWidgetContextKeys = {
Visible: new RawContextKey(
'codeActionMenuVisible',
false,
localize('codeActionMenuVisible', 'Whether the action widget list is visible'),
),
};
export const IActionWidgetService = createDecorator('actionWidgetService');
let ActionWidgetService = class ActionWidgetService extends Disposable {
contextViewService;
_contextKeyService;
_instantiationService;
get isVisible() {
return ActionWidgetContextKeys.Visible.getValue(this._contextKeyService) || false;
}
_list = this._register(new MutableDisposable());
constructor(contextViewService, _contextKeyService, _instantiationService) {
super();
this.contextViewService = contextViewService;
this._contextKeyService = _contextKeyService;
this._instantiationService = _instantiationService;
}
async show(user, supportsPreview, items, delegate, anchor, container, actionBarActions) {
const visibleContext = ActionWidgetContextKeys.Visible.bindTo(this._contextKeyService);
const list = this._instantiationService.createInstance(ActionList, user, supportsPreview, items, delegate);
this.contextViewService.showContextView(
{
getAnchor: () => anchor,
render: (container) => {
visibleContext.set(true);
return this._renderWidget(container, list, actionBarActions ?? []);
},
onHide: (didCancel) => {
visibleContext.reset();
return this._onWidgetClosed(didCancel);
},
},
container,
false,
);
}
acceptSelected(preview) {
this._list.value?.acceptSelected(preview);
}
focusPrevious() {
this._list?.value?.focusPrevious();
}
focusNext() {
this._list?.value?.focusNext();
}
hide() {
this._list.value?.hide();
this._list.clear();
}
clear() {
this._list.clear();
}
_renderWidget(element, list, actionBarActions) {
const widget = document.createElement('div');
widget.classList.add('action-widget');
element.appendChild(widget);
this._list.value = list;
if (this._list.value) {
widget.appendChild(this._list.value.domNode);
} else {
throw new Error('List has no value');
}
const renderDisposables = new DisposableStore();
// Invisible div to block mouse interaction in the rest of the UI
const menuBlock = document.createElement('div');
const block = element.appendChild(menuBlock);
block.classList.add('context-view-block');
renderDisposables.add(dom.addDisposableListener(block, dom.EventType.MOUSE_DOWN, (e) => e.stopPropagation()));
// Invisible div to block mouse interaction with the menu
const pointerBlockDiv = document.createElement('div');
const pointerBlock = element.appendChild(pointerBlockDiv);
pointerBlock.classList.add('context-view-pointerBlock');
// Removes block on click INSIDE widget or ANY mouse movement
renderDisposables.add(
dom.addDisposableListener(pointerBlock, dom.EventType.POINTER_MOVE, () => pointerBlock.remove()),
);
renderDisposables.add(
dom.addDisposableListener(pointerBlock, dom.EventType.MOUSE_DOWN, () => pointerBlock.remove()),
);
// Action bar
let actionBarWidth = 0;
if (actionBarActions.length) {
const actionBar = this._createActionBar('.action-widget-action-bar', actionBarActions);
if (actionBar) {
widget.appendChild(actionBar.getContainer().parentElement);
renderDisposables.add(actionBar);
actionBarWidth = actionBar.getContainer().offsetWidth;
}
}
const width = this._list.value?.layout(actionBarWidth);
widget.style.width = `${width}px`;
const focusTracker = renderDisposables.add(dom.trackFocus(element));
renderDisposables.add(focusTracker.onDidBlur(() => this.hide()));
return renderDisposables;
}
_createActionBar(className, actions) {
if (!actions.length) {
return undefined;
}
const container = dom.$(className);
const actionBar = new ActionBar(container);
actionBar.push(actions, { icon: false, label: true });
return actionBar;
}
_onWidgetClosed(didCancel) {
this._list.value?.hide(didCancel);
}
};
ActionWidgetService = __decorate(
[__param(0, IContextViewService), __param(1, IContextKeyService), __param(2, IInstantiationService)],
ActionWidgetService,
);
registerSingleton(IActionWidgetService, ActionWidgetService, 1 /* InstantiationType.Delayed */);
const weight = 100 /* KeybindingWeight.EditorContrib */ + 1000;
registerAction2(
class extends Action2 {
constructor() {
super({
id: 'hideCodeActionWidget',
title: {
value: localize('hideCodeActionWidget.title', 'Hide action widget'),
original: 'Hide action widget',
},
precondition: ActionWidgetContextKeys.Visible,
keybinding: {
weight,
primary: 9 /* KeyCode.Escape */,
secondary: [1024 /* KeyMod.Shift */ | 9 /* KeyCode.Escape */],
},
});
}
run(accessor) {
accessor.get(IActionWidgetService).hide();
}
},
);
registerAction2(
class extends Action2 {
constructor() {
super({
id: 'selectPrevCodeAction',
title: {
value: localize('selectPrevCodeAction.title', 'Select previous action'),
original: 'Select previous action',
},
precondition: ActionWidgetContextKeys.Visible,
keybinding: {
weight,
primary: 16 /* KeyCode.UpArrow */,
secondary: [2048 /* KeyMod.CtrlCmd */ | 16 /* KeyCode.UpArrow */],
mac: {
primary: 16 /* KeyCode.UpArrow */,
secondary: [
2048 /* KeyMod.CtrlCmd */ | 16 /* KeyCode.UpArrow */,
256 /* KeyMod.WinCtrl */ | 46 /* KeyCode.KeyP */,
],
},
},
});
}
run(accessor) {
const widgetService = accessor.get(IActionWidgetService);
if (widgetService instanceof ActionWidgetService) {
widgetService.focusPrevious();
}
}
},
);
registerAction2(
class extends Action2 {
constructor() {
super({
id: 'selectNextCodeAction',
title: {
value: localize('selectNextCodeAction.title', 'Select next action'),
original: 'Select next action',
},
precondition: ActionWidgetContextKeys.Visible,
keybinding: {
weight,
primary: 18 /* KeyCode.DownArrow */,
secondary: [2048 /* KeyMod.CtrlCmd */ | 18 /* KeyCode.DownArrow */],
mac: {
primary: 18 /* KeyCode.DownArrow */,
secondary: [
2048 /* KeyMod.CtrlCmd */ | 18 /* KeyCode.DownArrow */,
256 /* KeyMod.WinCtrl */ | 44 /* KeyCode.KeyN */,
],
},
},
});
}
run(accessor) {
const widgetService = accessor.get(IActionWidgetService);
if (widgetService instanceof ActionWidgetService) {
widgetService.focusNext();
}
}
},
);
registerAction2(
class extends Action2 {
constructor() {
super({
id: acceptSelectedActionCommand,
title: {
value: localize('acceptSelected.title', 'Accept selected action'),
original: 'Accept selected action',
},
precondition: ActionWidgetContextKeys.Visible,
keybinding: {
weight,
primary: 3 /* KeyCode.Enter */,
secondary: [2048 /* KeyMod.CtrlCmd */ | 84 /* KeyCode.Period */],
},
});
}
run(accessor) {
const widgetService = accessor.get(IActionWidgetService);
if (widgetService instanceof ActionWidgetService) {
widgetService.acceptSelected();
}
}
},
);
registerAction2(
class extends Action2 {
constructor() {
super({
id: previewSelectedActionCommand,
title: {
value: localize('previewSelected.title', 'Preview selected action'),
original: 'Preview selected action',
},
precondition: ActionWidgetContextKeys.Visible,
keybinding: {
weight,
primary: 2048 /* KeyMod.CtrlCmd */ | 3 /* KeyCode.Enter */,
},
});
}
run(accessor) {
const widgetService = accessor.get(IActionWidgetService);
if (widgetService instanceof ActionWidgetService) {
widgetService.acceptSelected(true);
}
}
},
);