识别上下文菜单命令的 VS Code Webview 实例

问题描述 投票:0回答:1

我正在构建一个可以创建多个 webview 的 VS Code 扩展;每个文本编辑器文档都可以有一个关联的 webview。我希望用户能够在 web 视图中右键单击并执行命令。该命令必须知道在其中单击了哪个 webview 实例才能做正确的事。

上下文菜单回调仅接收

{webview:<viewType>}
作为参数。
如何确定上下文菜单源自哪个 webview?

如果有帮助,以下是简化的扩展代码,显示我如何为每个

document.uri
创建一个新的 webview(和关联的查看器管理器):

import * as vscode from 'vscode';
import {commands, TextEditor, window} from 'vscode';
import {Viewer} from './viewer';

export function activate(ctx: vscode.ExtensionContext) {
  let manager = new MyExtManager();
  const subs = ctx.subscriptions;
  subs.push(commands.registerCommand('myExt.show', () => {
    manager.showWebview(ctx.extensionUri);
  }));

  subs.push(commands.registerCommand('myExt.myCtxItem', (wv) => {
    // need some unique identifier here to locate original editor
    console.log(wv);
  }));
}

class MyExtManager {
  private viewerByDoc: Map<vscode.Uri, Viewer> = new Map();

  public showWebview(extensionURI: vscode.Uri) {
    const editor: TextEditor | undefined = window.activeTextEditor;
    const doc = editor?.document;

    if (doc && doc.languageId === "xml") {
      let viewerForDoc = this.viewerByDoc.get(doc.uri);
      if (viewerForDoc) {
        viewerForDoc.reveal();
      } else {
        const panel = vscode.window.createWebviewPanel(
          'myxmlviewer', `My Viewer for ${doc.uri}`,
          vscode.ViewColumn.Beside
        );
        panel.onDidDispose(() => this.viewerByDoc.delete(doc.uri));
        viewerForDoc = new Viewer(editor, panel)
        this.viewerByDoc.set(doc.uri, viewerForDoc);
      }
    }
  }
}

我调查过的事情:

  • 我不能使用
    vscode.window.active*
    ,因为没有像
    activeTextEditor
    那样查看活动网络视图的集合。
  • 我似乎找不到在显示 WebviewPanel 时获得回调的方法(给定编辑器焦点),或者我可以使用全局扩展来跟踪最新的。
  • 我似乎无法找到一种方法来检测上下文菜单的打开作为对 webview 的回调,或者我可以类似地将其存储为全局。

我能想到的唯一技巧是劫持

viewType
参数,使其对每个查看器实例都是唯一的。我找不到太多关于此参数的意图,但具有唯一值似乎是一种意外使用。


上下文菜单是通过

package.json
文件中的这些添加内容构建的:

{
  "contributes": {
    "commands": [
      {
        "category": "XML Viewer",
        "command": "myExt.show",
        "title": "Open to the Side"
      },
      {
        "category": "XML Viewer",
        "command": "myExt.myCtxItem",
        "title": "Do a Thing Here"
      },
    ],
    "menus": {
      "webview/context": [
        {
          "command": "myExt.myCtxItem",
          "group": "xmlViewer"
        }
      ]
    }
  }
}
visual-studio-code contextmenu vscode-extensions vscode-webview
1个回答
0
投票

想出办法:

创建WebviewPanel时,注册一个

onDidChangeViewState
回调。检查面板是否处于活动和可见状态,如果是,则用它覆盖单个变量。

public activeWebview: WebviewPanel | null = null;

// ...
panel.onDidChangeViewState(e => {
   if (panel.active && panel.visible) {
      this.activeWebview = panel;
   } else if (activeWebview===panel) {
      this.activeWebview = null;
   }
});

...然后在扩展的命令注册中使用它:

subs.push(commands.registerCommand('myExt.myCtxItem', () => {
   if (manager.activeWebview) {
      // ...
   }    
}));

我实际上做的工作比上面的多得多,因此如果与 webview 关联的

TextEditor
可用,命令仍然可用……但这超出了这个问题的范围。

© www.soinside.com 2019 - 2024. All rights reserved.