Scope custom editor and webview context keys to editor groups and global context (#213398)

Properly scope custom editor and webview context keys
This commit is contained in:
Benjamin Christopher Simmonds 2024-05-24 17:47:54 +02:00 committed by GitHub
parent b6c1b52bac
commit 1e1afd0dd7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 54 additions and 34 deletions

View file

@ -12,7 +12,6 @@ import { extname, isEqual } from 'vs/base/common/resources';
import { assertIsDefined } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
import { FileOperation, IFileService } from 'vs/platform/files/common/files';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@ -24,7 +23,7 @@ import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { CONTEXT_ACTIVE_CUSTOM_EDITOR_ID, CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CustomEditorCapabilities, CustomEditorInfo, CustomEditorInfoCollection, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { CustomEditorModelManager } from 'vs/workbench/contrib/customEditor/common/customEditorModelManager';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorGroup, IEditorGroupContextKeyProvider, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorResolverService, IEditorType, RegisteredEditorPriority } from 'vs/workbench/services/editor/common/editorResolverService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ContributedCustomEditors } from '../common/contributedCustomEditors';
@ -40,16 +39,12 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
private readonly _models = new CustomEditorModelManager();
private readonly _activeCustomEditorId: IContextKey<string>;
private readonly _focusedCustomEditorIsEditable: IContextKey<boolean>;
private readonly _onDidChangeEditorTypes = this._register(new Emitter<void>());
public readonly onDidChangeEditorTypes: Event<void> = this._onDidChangeEditorTypes.event;
private readonly _fileEditorFactory = Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).getFileEditorFactory();
constructor(
@IContextKeyService contextKeyService: IContextKeyService,
@IFileService fileService: IFileService,
@IStorageService storageService: IStorageService,
@IEditorService private readonly editorService: IEditorService,
@ -60,9 +55,6 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
) {
super();
this._activeCustomEditorId = CONTEXT_ACTIVE_CUSTOM_EDITOR_ID.bindTo(contextKeyService);
this._focusedCustomEditorIsEditable = CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE.bindTo(contextKeyService);
this._contributedEditors = this._register(new ContributedCustomEditors(storageService));
// Register the contribution points only emitting one change from the resolver
this.editorResolverService.bufferChangeEvents(this.registerContributionPoints.bind(this));
@ -70,10 +62,25 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
this._register(this._contributedEditors.onChange(() => {
// Register the contribution points only emitting one change from the resolver
this.editorResolverService.bufferChangeEvents(this.registerContributionPoints.bind(this));
this.updateContexts();
this._onDidChangeEditorTypes.fire();
}));
this._register(this.editorService.onDidActiveEditorChange(() => this.updateContexts()));
// Register group context key providers.
// These set the context keys for each editor group and the global context
const activeCustomEditorContextKeyProvider: IEditorGroupContextKeyProvider<string> = {
contextKey: CONTEXT_ACTIVE_CUSTOM_EDITOR_ID,
getGroupContextKeyValue: group => this.getActiveCustomEditorId(group),
onDidChange: this.onDidChangeEditorTypes
};
const customEditorIsEditableContextKeyProvider: IEditorGroupContextKeyProvider<boolean> = {
contextKey: CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE,
getGroupContextKeyValue: group => this.getCustomEditorIsEditable(group),
onDidChange: this.onDidChangeEditorTypes
};
this._register(this.editorGroupService.registerContextKeyProvider(activeCustomEditorContextKeyProvider));
this._register(this.editorGroupService.registerContextKeyProvider(customEditorIsEditableContextKeyProvider));
this._register(fileService.onDidRunOperation(e => {
if (e.isOperation(FileOperation.MOVE)) {
@ -88,8 +95,6 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
this._register(RedoCommand.addImplementation(PRIORITY, 'custom-editor', () => {
return this.withActiveCustomEditor(editor => editor.redo());
}));
this.updateContexts();
}
getEditorTypes(): IEditorType[] {
@ -193,17 +198,24 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
return this._editorCapabilities.get(viewType);
}
private updateContexts() {
const activeEditorPane = this.editorService.activeEditorPane;
private getActiveCustomEditorId(group: IEditorGroup): string {
const activeEditorPane = group.activeEditorPane;
const resource = activeEditorPane?.input?.resource;
if (!resource) {
this._activeCustomEditorId.reset();
this._focusedCustomEditorIsEditable.reset();
return;
return '';
}
this._activeCustomEditorId.set(activeEditorPane?.input instanceof CustomEditorInput ? activeEditorPane.input.viewType : '');
this._focusedCustomEditorIsEditable.set(activeEditorPane?.input instanceof CustomEditorInput);
return activeEditorPane?.input instanceof CustomEditorInput ? activeEditorPane.input.viewType : '';
}
private getCustomEditorIsEditable(group: IEditorGroup): boolean {
const activeEditorPane = group.activeEditorPane;
const resource = activeEditorPane?.input?.resource;
if (!resource) {
return false;
}
return activeEditorPane?.input instanceof CustomEditorInput;
}
private async handleMovedFileInOpenedFileEditors(oldResource: URI, newResource: URI): Promise<void> {

View file

@ -10,7 +10,6 @@ import { isCancellationError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { Iterable } from 'vs/base/common/iterator';
import { combinedDisposable, Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { EditorActivation } from 'vs/platform/editor/common/editor';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { GroupIdentifier } from 'vs/workbench/common/editor';
@ -19,7 +18,7 @@ import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { IOverlayWebview, IWebviewService, WebviewInitInfo } from 'vs/workbench/contrib/webview/browser/webview';
import { CONTEXT_ACTIVE_WEBVIEW_PANEL_ID } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditor';
import { WebviewIconManager, WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService';
import { WebviewInput, WebviewInputInitInfo } from './webviewEditorInput';
@ -213,20 +212,21 @@ export class WebviewEditorService extends Disposable implements IWebviewWorkbenc
private readonly _iconManager: WebviewIconManager;
private readonly _activeWebviewPanelIdContext: IContextKey<string>;
constructor(
@IContextKeyService contextKeyService: IContextKeyService,
@IEditorGroupsService editorGroupsService: IEditorGroupsService,
@IEditorService private readonly _editorService: IEditorService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IWebviewService private readonly _webviewService: IWebviewService,
) {
super();
this._activeWebviewPanelIdContext = CONTEXT_ACTIVE_WEBVIEW_PANEL_ID.bindTo(contextKeyService);
this._iconManager = this._register(this._instantiationService.createInstance(WebviewIconManager));
this._register(editorGroupsService.registerContextKeyProvider({
contextKey: CONTEXT_ACTIVE_WEBVIEW_PANEL_ID,
getGroupContextKeyValue: (group) => this.getWebviewId(group.activeEditor),
}));
this._register(_editorService.onDidActiveEditorChange(() => {
this.updateActiveWebview();
}));
@ -248,6 +248,21 @@ export class WebviewEditorService extends Disposable implements IWebviewWorkbenc
private readonly _onDidChangeActiveWebviewEditor = this._register(new Emitter<WebviewInput | undefined>());
public readonly onDidChangeActiveWebviewEditor = this._onDidChangeActiveWebviewEditor.event;
private getWebviewId(input: EditorInput | null): string {
let webviewInput: WebviewInput | undefined;
if (input instanceof WebviewInput) {
webviewInput = input;
} else if (input instanceof DiffEditorInput) {
if (input.primary instanceof WebviewInput) {
webviewInput = input.primary;
} else if (input.secondary instanceof WebviewInput) {
webviewInput = input.secondary;
}
}
return webviewInput?.webview.providedViewType ?? '';
}
private updateActiveWebview() {
const activeInput = this._editorService.activeEditor;
@ -261,13 +276,6 @@ export class WebviewEditorService extends Disposable implements IWebviewWorkbenc
newActiveWebview = activeInput.secondary;
}
}
if (newActiveWebview) {
this._activeWebviewPanelIdContext.set(newActiveWebview.webview.providedViewType ?? '');
} else {
this._activeWebviewPanelIdContext.reset();
}
if (newActiveWebview !== this._activeWebview) {
this._activeWebview = newActiveWebview;
this._onDidChangeActiveWebviewEditor.fire(newActiveWebview);