Skip to content

Commit

Permalink
Scope custom editor and webview context keys to editor groups and glo…
Browse files Browse the repository at this point in the history
…bal context (microsoft#213398)

Properly scope custom editor and webview context keys
  • Loading branch information
benibenj authored and andremmsilva committed May 26, 2024
1 parent 20225b8 commit d9705b4
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 34 deletions.
52 changes: 32 additions & 20 deletions src/vs/workbench/contrib/customEditor/browser/customEditors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand All @@ -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,
Expand All @@ -60,20 +55,32 @@ 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));

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)) {
Expand All @@ -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[] {
Expand Down Expand Up @@ -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 '';
}

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;
}

this._activeCustomEditorId.set(activeEditorPane?.input instanceof CustomEditorInput ? activeEditorPane.input.viewType : '');
this._focusedCustomEditorIsEditable.set(activeEditorPane?.input instanceof CustomEditorInput);
return activeEditorPane?.input instanceof CustomEditorInput;
}

private async handleMovedFileInOpenedFileEditors(oldResource: URI, newResource: URI): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';

Expand Down Expand Up @@ -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();
}));
Expand All @@ -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;

Expand All @@ -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);
Expand Down

0 comments on commit d9705b4

Please sign in to comment.