From 784de603197348d570857adf3a306b3b92deea1f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Tue, 2 Aug 2022 22:03:33 -0700 Subject: [PATCH] Add `activeWebviewPanelId` context key (#156944) Fixes #156942 This context tracks the id of the active webviewPanel --- .../markdown-language-features/package.json | 16 ++++++++-------- .../src/preview/previewManager.ts | 8 -------- .../api/browser/mainThreadWebviewPanels.ts | 2 +- .../customEditor/browser/customEditorInput.ts | 2 +- .../browser/customEditorInputFactory.ts | 2 +- .../contrib/webview/browser/overlayWebview.ts | 6 +++--- .../contrib/webview/browser/webview.ts | 5 +++++ .../contrib/webview/browser/webviewElement.ts | 11 +++++------ .../webviewPanel/browser/webviewEditor.ts | 11 ++++++++++- .../browser/webviewEditorInputSerializer.ts | 2 +- .../browser/webviewWorkbenchService.ts | 17 +++++++++++++++-- .../webviewView/browser/webviewViewPane.ts | 2 +- 12 files changed, 51 insertions(+), 33 deletions(-) diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index cae88bf134f..ffa9336499b 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -187,22 +187,22 @@ }, { "command": "markdown.showSource", - "when": "markdownPreviewFocus", + "when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'", "group": "navigation" }, { "command": "markdown.preview.refresh", - "when": "markdownPreviewFocus", + "when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'", "group": "1_markdown" }, { "command": "markdown.preview.toggleLock", - "when": "markdownPreviewFocus", + "when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'", "group": "1_markdown" }, { "command": "markdown.showPreviewSecuritySelector", - "when": "markdownPreviewFocus", + "when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'", "group": "1_markdown" } ], @@ -247,7 +247,7 @@ }, { "command": "markdown.showSource", - "when": "markdownPreviewFocus", + "when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'", "group": "navigation" }, { @@ -256,11 +256,11 @@ }, { "command": "markdown.showPreviewSecuritySelector", - "when": "markdownPreviewFocus" + "when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'" }, { "command": "markdown.preview.toggleLock", - "when": "markdownPreviewFocus" + "when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'" }, { "command": "markdown.preview.refresh", @@ -268,7 +268,7 @@ }, { "command": "markdown.preview.refresh", - "when": "markdownPreviewFocus" + "when": "activeWebviewPanelId == 'markdown.preview' || activeCustomEditorId == 'vscode.markdown.preview.editor'" }, { "command": "markdown.findAllFileReferences", diff --git a/extensions/markdown-language-features/src/preview/previewManager.ts b/extensions/markdown-language-features/src/preview/previewManager.ts index 134989ce181..3faa0f63b0f 100644 --- a/extensions/markdown-language-features/src/preview/previewManager.ts +++ b/extensions/markdown-language-features/src/preview/previewManager.ts @@ -58,8 +58,6 @@ class PreviewStore extends Disposable { export class MarkdownPreviewManager extends Disposable implements vscode.WebviewPanelSerializer, vscode.CustomTextEditorProvider { - private static readonly markdownPreviewActiveContextKey = 'markdownPreviewFocus'; - private readonly _topmostLineMonitor = new TopmostLineMonitor(); private readonly _previewConfigurations = new MarkdownPreviewConfigurationManager(); @@ -216,7 +214,6 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview this._contributions, this._tocProvider); - this.setPreviewActiveContext(true); this._activePreview = preview; return this.registerDynamicPreview(preview); } @@ -250,19 +247,14 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview private trackActive(preview: IManagedMarkdownPreview): void { preview.onDidChangeViewState(({ webviewPanel }) => { - this.setPreviewActiveContext(webviewPanel.active); this._activePreview = webviewPanel.active ? preview : undefined; }); preview.onDispose(() => { if (this._activePreview === preview) { - this.setPreviewActiveContext(false); this._activePreview = undefined; } }); } - private setPreviewActiveContext(value: boolean) { - vscode.commands.executeCommand('setContext', MarkdownPreviewManager.markdownPreviewActiveContextKey, value); - } } diff --git a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts index c8dd0761ef1..79a0765ef3e 100644 --- a/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts +++ b/src/vs/workbench/api/browser/mainThreadWebviewPanels.ts @@ -167,7 +167,7 @@ export class MainThreadWebviewPanels extends Disposable implements extHostProtoc const webview = this._webviewWorkbenchService.createWebview({ id: handle, - providedId: viewType, + providedViewType: viewType, options: reviveWebviewOptions(initData.panelOptions), contentOptions: reviveWebviewContentOptions(initData.webviewOptions), extension diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index a514a41b857..f5f1a414b18 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -46,7 +46,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { const id = generateUuid(); const webview = accessor.get(IWebviewService).createWebviewOverlay({ id, - providedId: viewType, + providedViewType: viewType, options: { customClasses: options?.customClasses }, contentOptions: {}, extension: undefined, diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts index 4277c67ab6a..e98fbb5a058 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts @@ -111,7 +111,7 @@ export class CustomEditorInputSerializer extends WebviewEditorInputSerializer { function reviveWebview(webviewService: IWebviewService, data: { id: string; origin: string | undefined; viewType: string; state: any; webviewOptions: WebviewOptions; contentOptions: WebviewContentOptions; extension?: WebviewExtensionDescription }) { const webview = webviewService.createWebviewOverlay({ id: data.id, - providedId: data.viewType, + providedViewType: data.viewType, origin: data.origin, options: { purpose: WebviewContentPurpose.CustomEditor, diff --git a/src/vs/workbench/contrib/webview/browser/overlayWebview.ts b/src/vs/workbench/contrib/webview/browser/overlayWebview.ts index 81499a931b6..3eeb445b292 100644 --- a/src/vs/workbench/contrib/webview/browser/overlayWebview.ts +++ b/src/vs/workbench/contrib/webview/browser/overlayWebview.ts @@ -44,7 +44,7 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { private _findWidgetEnabled: IContextKey | undefined; public readonly id: string; - public readonly providedId?: string; + public readonly providedViewType?: string; public readonly origin: string; public constructor( @@ -56,7 +56,7 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { super(); this.id = initInfo.id; - this.providedId = initInfo.providedId; + this.providedViewType = initInfo.providedViewType; this.origin = initInfo.origin ?? generateUuid(); this._extension = initInfo.extension; @@ -194,7 +194,7 @@ export class OverlayWebview extends Disposable implements IOverlayWebview { if (!this._webview.value) { const webview = this._webviewService.createWebviewElement({ id: this.id, - providedId: this.providedId, + providedViewType: this.providedViewType, origin: this.origin, options: this._options, contentOptions: this._contentOptions, diff --git a/src/vs/workbench/contrib/webview/browser/webview.ts b/src/vs/workbench/contrib/webview/browser/webview.ts index e9e90223d4e..83296c95ac4 100644 --- a/src/vs/workbench/contrib/webview/browser/webview.ts +++ b/src/vs/workbench/contrib/webview/browser/webview.ts @@ -161,6 +161,11 @@ export interface IWebview extends IDisposable { */ readonly origin: string; + /** + * The original view type of the webview. + */ + readonly providedViewType?: string; + html: string; contentOptions: WebviewContentOptions; localResourcesRoot: readonly URI[]; diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts index 465ab3b4681..73c6baaf38e 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts @@ -102,7 +102,7 @@ namespace WebviewState { export interface WebviewInitInfo { readonly id: string; - readonly providedId?: string; + readonly providedViewType?: string; readonly origin?: string; readonly options: WebviewOptions; @@ -123,11 +123,10 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD */ public readonly id: string; - /** * The provided identifier of this webview. */ - public readonly providedId?: string; + public readonly providedViewType?: string; /** * The origin this webview itself is loaded from. May not be unique @@ -210,7 +209,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD super(); this.id = initInfo.id; - this.providedId = initInfo.providedId; + this.providedViewType = initInfo.providedViewType; this.iframeId = generateUuid(); this.origin = initInfo.origin ?? this.iframeId; @@ -343,7 +342,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD getActions: () => { const contextKeyService = this._contextKeyService!.createOverlay([ ...Object.entries(data.context), - ['webview', this.providedId], + ['webview', this.providedViewType], ]); const result: IAction[] = []; @@ -352,7 +351,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD menu.dispose(); return result; }, - getActionsContext: (): WebviewActionContext => ({ ...data.context, webview: this.providedId }), + getActionsContext: (): WebviewActionContext => ({ ...data.context, webview: this.providedViewType }), getAnchor: () => ({ x: elementBox.x + data.clientX, y: elementBox.y + data.clientY diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts index 5b6a38cba23..d804ab85570 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts @@ -9,7 +9,8 @@ import { Emitter, Event } from 'vs/base/common/event'; import { DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { isWeb } from 'vs/base/common/platform'; import { generateUuid } from 'vs/base/common/uuid'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import * as nls from 'vs/nls'; +import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IEditorOptions } from 'vs/platform/editor/common/editor'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -26,6 +27,14 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService'; +/** + * Tracks the id of the actively focused webview. + */ +export const CONTEXT_ACTIVE_WEBVIEW_PANEL_ID = new RawContextKey('activeWebviewPanelId', '', { + type: 'string', + description: nls.localize('context.activeWebviewId', "The viewType of the currently active webview panel."), +}); + export class WebviewEditor extends EditorPane { public static readonly ID = 'WebviewEditor'; diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInputSerializer.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInputSerializer.ts index 483a6b37bc9..9adca06119c 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInputSerializer.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInputSerializer.ts @@ -80,7 +80,7 @@ export class WebviewEditorInputSerializer implements IEditorSerializer { return this._webviewWorkbenchService.reviveWebview({ webviewInitInfo: { id: data.id, - providedId: data.providedId, + providedViewType: data.providedId, origin: data.origin, options: data.webviewOptions, contentOptions: data.contentOptions, diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService.ts index 00232b050e9..97e206c6ec9 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService.ts @@ -10,6 +10,7 @@ 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'; @@ -17,6 +18,7 @@ import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { IOverlayWebview, IWebviewService } from 'vs/workbench/contrib/webview/browser/webview'; import { WebviewInitInfo } from 'vs/workbench/contrib/webview/browser/webviewElement'; +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 { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; @@ -185,13 +187,18 @@ export class WebviewEditorService extends Disposable implements IWebviewWorkbenc private readonly _iconManager: WebviewIconManager; + private readonly _activeWebviewPanelIdContext: IContextKey; + constructor( + @IContextKeyService contextKeyService: IContextKeyService, @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(_editorService.onDidActiveEditorChange(() => { @@ -229,6 +236,12 @@ export class WebviewEditorService extends Disposable implements IWebviewWorkbenc } } + if (newActiveWebview) { + this._activeWebviewPanelIdContext.set(newActiveWebview.webview.providedViewType ?? ''); + } else { + this._activeWebviewPanelIdContext.reset(); + } + if (newActiveWebview !== this._activeWebview) { this._activeWebview = newActiveWebview; this._onDidChangeActiveWebviewEditor.fire(newActiveWebview); @@ -242,7 +255,7 @@ export class WebviewEditorService extends Disposable implements IWebviewWorkbenc showOptions: ICreateWebViewShowOptions, ): WebviewInput { const webview = this._webviewService.createWebviewOverlay(webviewInitInfo); - const webviewInput = this._instantiationService.createInstance(WebviewInput, { id: webviewInitInfo.id, viewType, name: title, providedId: webviewInitInfo.providedId }, webview, this.iconManager); + const webviewInput = this._instantiationService.createInstance(WebviewInput, { id: webviewInitInfo.id, viewType, name: title, providedId: webviewInitInfo.providedViewType }, webview, this.iconManager); this._editorService.openEditor(webviewInput, { pinned: true, preserveFocus: showOptions.preserveFocus, @@ -293,7 +306,7 @@ export class WebviewEditorService extends Disposable implements IWebviewWorkbenc const webview = this._webviewService.createWebviewOverlay(options.webviewInitInfo); webview.state = options.state; - const webviewInput = this._instantiationService.createInstance(LazilyResolvedWebviewEditorInput, { id: options.webviewInitInfo.id, viewType: options.viewType, providedId: options.webviewInitInfo.providedId, name: options.title }, webview); + const webviewInput = this._instantiationService.createInstance(LazilyResolvedWebviewEditorInput, { id: options.webviewInitInfo.id, viewType: options.viewType, providedId: options.webviewInitInfo.providedViewType, name: options.title }, webview); webviewInput.iconPath = options.iconPath; if (typeof options.group === 'number') { diff --git a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts index 9a149dca7ee..d72f98cb736 100644 --- a/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts +++ b/src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts @@ -169,7 +169,7 @@ export class WebviewViewPane extends ViewPane { const webviewId = generateUuid(); const webview = this.webviewService.createWebviewOverlay({ id: webviewId, - providedId: this.id, + providedViewType: this.id, options: { purpose: WebviewContentPurpose.WebviewView }, contentOptions: {}, extension: this.extensionId ? { id: this.extensionId } : undefined