Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Notebook Renderer Messaging #19

Open
mikeburgh opened this issue Feb 10, 2024 · 4 comments
Open

Notebook Renderer Messaging #19

mikeburgh opened this issue Feb 10, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@mikeburgh
Copy link

Great library, especially the request functionality.

Any thoughts about supporting notebook messaging with their custom renderer's ?

Notebooks use vscode.NotebookRendererMessaging on the extension side, which contains the postMessage and onDidReceiveMessage and is bound to a single notebook renderer on creation.

On the renderer instead of using acquireVsCodeApi, the activation function of the notebook renderer gets passed a context (RendererContext) which contains postMessage and onDidReceiveMessage.

@dhuebner dhuebner added the enhancement New feature or request label Feb 12, 2024
@dhuebner
Copy link
Member

@mikeburgh
Did you get around this limitation, or do you still need some additional API on the messenger side?

@mikeburgh
Copy link
Author

Got it around it, yes.. I use the library and wrap a few parts to make it work with notebooks (basically intercept the notebook messaging, and then feed it into the vscode-messenger).

The other thing that makes notebooks tricky, and it might just be my use case, but I need to target specific cells within the notebook, not just all cells in some cases.

Ideally it could be treated like the way you can target webviews or all webviews if you look to add this into the main library.

@dhuebner
Copy link
Member

@mikeburgh

Ideally it could be treated like the way you can target webviews or all webviews if you look to add this into the main library.

You can use webviewIds instead of webviewType for that, or is that even more fine-grained?

/**
* A webview must be identified either with an ID (`webviewId`) or a type (`webviewType`).
*/
export type WebviewMessageParticipant = WebviewIdMessageParticipant | WebviewTypeMessageParticipant;
export interface WebviewIdMessageParticipant {
type: 'webview'
/** Identifier of a specific webview instance. */
webviewId: string
}
export function isWebviewIdMessageParticipant(participant: MessageParticipant): participant is WebviewIdMessageParticipant {
return participant.type === 'webview' && typeof (participant as WebviewIdMessageParticipant).webviewId === 'string';
}
export interface WebviewTypeMessageParticipant {
type: 'webview'
/** Webview panel type or webview view type. */
webviewType: string
}
export function isWebviewTypeMessageParticipant(participant: MessageParticipant): participant is WebviewTypeMessageParticipant {

@mikeburgh
Copy link
Author

@dhuebner even more finegrained.

As I understand it, the notebook output cells are all in the same "webview" and just moved around to position under the input cells. They use a different activation method than the standard webview (aquireVSCodeAPI) to get the window messaging methods, you can see it here: https://code.visualstudio.com/api/extension-guides/notebook#interactive-notebooks-communicating-with-the-extension-host

Then within the "webview" iframe that is used for the notebook output renderer, there are multiple cells so being able to target them individually is key.

I have a solution that works, and leverages most of the plumbing from this lib, so I can live with it as it is... This is basically what I have done:

// Listen for messages from the notebook controller
this.listener = this.context.onDidReceiveMessage(async (message: any) => {
	if (message.cellId === this.metadata.id) {
                //It's a match for this cell!

		const { cellId, ...data } = message;

                //Handle any that need to respond.
		switch (message.method) {
			case executionMsg.method: {

				//Do some work..

				//@ts-expect-error it's protected, but we need to use it to get to the right mesasge flow!
				WebViewGlobal.messenger.vscode.postMessage({
					id: message.id,
					receiver: message.sender,
					result: 'Something to send back',
				});

				return;
			}
			case gridStateGet.method: {
				
				//Do some work..

				//@ts-expect-error it's protected, but we need to use it to get to the right mesasge flow!
				WebViewGlobal.messenger.vscode.postMessage({
					id: message.id,
					receiver: message.sender,
					result,
				});
				return;
			}
		}

		//It's not one we need to reply to, but still specific to this cell, run it!
		data.receiver = { type: 'notebook' };
		//@ts-expect-error It's protected, but we need to use it to get to the right mesasge flow!
		WebViewGlobal.messenger.processMessage(data);
	} else if (message.cellId === undefined && message.method === 'settingChange') {
		//This one is not targeting any cell but all cells, push it through
		const data = message;
		data.receiver = { type: 'notebook' };
		//@ts-expect-error It's protected, but we need to use it to get to the right mesasge flow!
		WebViewGlobal.messenger.processMessage(data);
	}
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants