Add activeWebviewPanelId context key (#156944)

Fixes #156942

This context tracks the id of the active webviewPanel
This commit is contained in:
Matt Bierner 2022-08-02 22:03:33 -07:00 committed by GitHub
parent 7833aade5a
commit 784de60319
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 51 additions and 33 deletions

View file

@ -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",

View file

@ -58,8 +58,6 @@ class PreviewStore<T extends IManagedMarkdownPreview> 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);
}
}

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -44,7 +44,7 @@ export class OverlayWebview extends Disposable implements IOverlayWebview {
private _findWidgetEnabled: IContextKey<boolean> | 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,

View file

@ -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[];

View file

@ -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

View file

@ -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<string>('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';

View file

@ -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,

View file

@ -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<string>;
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') {

View file

@ -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