UNPKG

@sussudio/platform

Version:

Internal APIs for VS Code's service injection the base services.

290 lines (289 loc) 9.68 kB
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); } } }, );