microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
162.66k stars 28.69k forks source link

Better UI extensibility: retain webviews, provide communication channel #28263

Closed pavelfeldman closed 6 years ago

pavelfeldman commented 7 years ago

I was looking at porting some of the Chrome DevTools features over to VSCode: timeline / profiler to start with, maybe elements / sidebar.

All my controls have rich UI that I would like to surface either as editors or as views in the console drawer. I was using TextDocumentContentProvider to render my content. Some of the limitations of the extensibility system I hit were:

jrieken commented 7 years ago

The design of VS Code is to not allow for UI extensions on that level but our API defined data contracts where extensions fill in data and the editor renderers it. In fact, extensions run in a separate, headless process to guarantee isolation. See https://code.visualstudio.com/docs/extensionAPI/patterns-and-principles#_our-approach-to-extensibility for all the details.

pavelfeldman commented 7 years ago

Yes, I'm familiar with the existing policy and I am suggesting to extend it. I was thinking of making parts of Chrome DevTools work in VSCode environment as well (I'm TL of the Chrome DevTools team). And present UI extensibility model feels rather limiting. More than that, I can get pretty far with the existing policy:

But the experiences I create end up sub-optimal, at the expense of the user. If you think your longer term goal is to allow richer UI extensibility, I can look into the browser limitations that prevent you from getting there. Oopifs should allow security and performance isolation sufficient to run extensions in the UI without compromising your core experience. I know reparenting is not there, but it is more important if you are willing to get there. Alternatively, if at this point you are strong on not letting features such as Chrome's performance tooling into your framework as extensions, I'll drop the idea altogether.

egamma commented 7 years ago

@pavelfeldman we are definitely interested in experiments in this area. I'll look into this in our side and I will get back to you.

egamma commented 7 years ago

@pavelfeldman having the Chrome DevTools performance tooling available inside VS Code is very interesting to us. What do you think of the approach of pushing the integration as far as we can get with the current support and then we collaborate on improving the experience and the extension API.

I suggest to start with an integration of the perf tools in an editor using the existing htmlPreview support. This is similar to what we did for the SQL extension. The SQL extension provides rich UI to present query results. The SQL externalizes the state into an express server.

I'm adding some team members that can chime in if you are game to start on this and you have more questions: @jrieken htmlPreview API @weinand debugger architecture and protocol @roblourens chrome debugger extension

jrieken commented 7 years ago

Ok, lets brainstorm more on this. As you have said, the document provider and preview command is a way of making custom UI but was definitely not designed for that. It is what its name implies, previewing a resource. We acknowledge that it's used for building UI and time to make this more official and supported will come. We had similar ideas, in short along those lines

An API could look like this

interface Webview {
    readonly name: string;
    location: ViewColumn;
    markup: string;
    onDidReceiveMessage: Event<any>;
    sendMessage(message: any): Thenable<any>;
    dispose(): void;
}

export function createWebview(name: string): Webview;

Reasons why we haven't pursued that idea yet are

In short, many questions and tradeoffs. @pavelfeldman - I'd like to hear your thoughts on this.

petrbrzek commented 6 years ago

Is this thing on the roadmap or it's not a priority right now? @egamma

ivankravets commented 6 years ago

This issue totally blocks @PlatformIO

egamma commented 6 years ago

@petrbrzek this is our current roadmap. There are some UI API improvements on there, but opening up VS Code for general UI extensibility is not on our 6-12 month roadmap.

With regard to WebView, given our focus on performance and stability, we will investigate intoBrowserViews.

egamma commented 6 years ago

@ivankravets what is the @platformio scenario that is blocked?

ivankravets commented 6 years ago

@egamma. @platformio has "PIO Home" web-based application written in React+Redux which developers use to manage embedded libraries, development platforms, and other things. PIO Home depends on backend server through WebSocket.

We have different extensions for different IDEs including for VSCode. Each IDE's extension launches own instance of PIO Home Server in the background and waits for a connection from WebView/IFrame components. It takes 2-5secs for the first loading (establish WebSocket connection ws://localhost:8xxx/yyy, configure PIO Home workspace).

Currently, we recommend using PlatformIO IDE for Atom because it can keep an opened tab with PIO Home. VSCode destroys PIO Home (with <IFRAME ../>) each time when developer switches between tabs. As result, they can't use it for the most operation because they need to wait 5 secs again and again. A temporary solution is to split VSCode into 2 vertical Layouts and keep PIO Home in one of them. However, that is not useful with small screens.

Finally, we plan to move a lot of features to PIO Home which makes it portable between different IDEs including desktop browsers. Indeed, we need just the one option which will allow explaining VSCode to don't destroy our IFRAME.

Thanks!

jrieken commented 6 years ago

VSCode destroys PIO Home (with <IFRAME ../>) each time when developer switches between tabs

Yeah, that unfortunate... Things run inside a webview-process because that isolates us well from extension code. The downside is that the process restarts whenever it is detached from the document, e.g reparented. This happens when you drag an editor around between two columns. It also seems to happens when selecting different tabs within an editor column. Not sure why, @bpasero might know if that on purpose or not

bpasero commented 6 years ago

@jrieken up to the editor to decide, when the tab gets hidden clearInput is called and most editors in that case dispose their resources because the editor is no longer visible, which imho is the right thing to do.

jrieken commented 6 years ago

Hm, this actually happens when calling setVisible(false)... Given that the webview is so fragile I'd tend to keep it alive when that happens.

bpasero commented 6 years ago

@jrieken isn't that against our principles in some way. We never sold the webview as something that survives longer sessions. I think an extension must assume that the contents come and go dynamically.

If we wanted to have a more stable webview container for extensions, it should imho be maybe a panel that the extension can add to our panel container.

jrieken commented 6 years ago

We never sold the webview as something that survives longer sessions.

I agree but this somehow became reality and I don't see a point in making it harder when there is already enough pain

bpasero commented 6 years ago

@jrieken maybe this becomes opt-in so that an extension can set a flag if a webview should survive editor changes?

bpasero commented 6 years ago

Actually one challenge will be that there could be multiple webviews open in one editor group and then that would mean to basically create multiple webviews for each extension that opened one.

ivankravets commented 6 years ago

maybe this becomes opt-in so that an extension can set a flag if a webview should survive editor changes?

This could help us a lot while you are looking for a better solution! Thanks!

jrieken commented 6 years ago

lot while you are looking for a better solution!

Well, there is no better solution tbh. Yes, we can tweak the behaviour when a tab changes but as soon as webviews are re-arranged (and thereby reparented) a restart will happen. We cannot change that unfortunately and I'd recommend to keep more state inside your server such that a reconnect is fast

ivankravets commented 6 years ago

d I'd recommend to keep more state inside your server such that a reconnect is fast

There is not the only problem with reconnecting. We need to re-paint whole React application according to the last state each time. It requires the seconds, not the milliseconds. It depends on user's machine too, need to load "index.html", init it and only after that try to connect to the end server...

mjbvz commented 6 years ago

@pavelfeldman I just checked in a new proposed webview API that addresses many of your points: https://github.com/Microsoft/vscode/blob/70b41f0b2dffe69f848abc0434bea9d2d11350a7/src/vs/vscode.proposed.d.ts#L528

The proposal introduces an option to keepAlive a webview so that its content not destroyed when the webview itself becomes hidden, as well as adding an official message passing API. Please take a look at the proposal and let me know if you have any questions or suggestions

ivankravets commented 6 years ago

The proposal introduces an option to keepAlive a webview

We can't wait to see this feature in the final release. We have over 100K downloads of our extennsion for the last months and each time users ask us about https://github.com/platformio/platformio-vscode-ide/issues/32

eamodio commented 6 years ago

Looks great! The onBecame* feels odd to me compared with the rest of the API tho. Maybe onDidActivate & onDidDeactivate. Also maybe onMessage could be onDidReceiveMessage

auchenberg commented 6 years ago

Would the visibility events be modeled after https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API @mattbierner? I assume the postMessage is modeled after https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage