mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode e1d3dd53d17fb1529a002e4d6fb066db0a0bd385 (#6460)
* Merge from vscode e1d3dd53d17fb1529a002e4d6fb066db0a0bd385 * fix servers icon * fix tests
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IWebviewService, Webview, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/common/webview';
|
||||
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
|
||||
/**
|
||||
* Webview editor overlay that creates and destroys the underlying webview as needed.
|
||||
*/
|
||||
export class DynamicWebviewEditorOverlay extends Disposable implements WebviewEditorOverlay {
|
||||
|
||||
private readonly _pendingMessages = new Set<any>();
|
||||
private readonly _webview = this._register(new MutableDisposable<WebviewElement>());
|
||||
private readonly _webviewEvents = this._register(new DisposableStore());
|
||||
|
||||
private _html: string = '';
|
||||
private _initialScrollProgress: number = 0;
|
||||
private _state: string | undefined = undefined;
|
||||
private _owner: any = undefined;
|
||||
|
||||
public constructor(
|
||||
private readonly id: string,
|
||||
public readonly options: WebviewOptions,
|
||||
private _contentOptions: WebviewContentOptions,
|
||||
@IWorkbenchLayoutService private readonly _layoutService: IWorkbenchLayoutService,
|
||||
@IWebviewService private readonly _webviewService: IWebviewService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._register(toDisposable(() => this.container.remove()));
|
||||
}
|
||||
|
||||
@memoize
|
||||
public get container() {
|
||||
const container = document.createElement('div');
|
||||
container.id = `webview-${this.id}`;
|
||||
this._layoutService.getContainer(Parts.EDITOR_PART).appendChild(container);
|
||||
return container;
|
||||
}
|
||||
|
||||
public claim(owner: any) {
|
||||
this._owner = owner;
|
||||
this.show();
|
||||
}
|
||||
|
||||
public release(owner: any) {
|
||||
if (this._owner !== owner) {
|
||||
return;
|
||||
}
|
||||
this._owner = undefined;
|
||||
this.container.style.visibility = 'hidden';
|
||||
if (!this.options.retainContextWhenHidden) {
|
||||
this._webview.clear();
|
||||
this._webviewEvents.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private show() {
|
||||
if (!this._webview.value) {
|
||||
const webview = this._webviewService.createWebview(this.id, this.options, this._contentOptions);
|
||||
this._webview.value = webview;
|
||||
webview.state = this._state;
|
||||
webview.html = this._html;
|
||||
if (this.options.tryRestoreScrollPosition) {
|
||||
webview.initialScrollProgress = this._initialScrollProgress;
|
||||
}
|
||||
this._webview.value.mountTo(this.container);
|
||||
this._webviewEvents.clear();
|
||||
|
||||
webview.onDidFocus(() => { this._onDidFocus.fire(); }, undefined, this._webviewEvents);
|
||||
webview.onDidClickLink(x => { this._onDidClickLink.fire(x); }, undefined, this._webviewEvents);
|
||||
webview.onMessage(x => { this._onMessage.fire(x); }, undefined, this._webviewEvents);
|
||||
|
||||
webview.onDidScroll(x => {
|
||||
this._initialScrollProgress = x.scrollYPercentage;
|
||||
this._onDidScroll.fire(x);
|
||||
}, undefined, this._webviewEvents);
|
||||
|
||||
webview.onDidUpdateState(state => {
|
||||
this._state = state;
|
||||
this._onDidUpdateState.fire(state);
|
||||
}, undefined, this._webviewEvents);
|
||||
|
||||
this._pendingMessages.forEach(msg => webview.sendMessage(msg));
|
||||
this._pendingMessages.clear();
|
||||
}
|
||||
this.container.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
public get html(): string { return this._html; }
|
||||
public set html(value: string) {
|
||||
this._html = value;
|
||||
this.withWebview(webview => webview.html = value);
|
||||
}
|
||||
|
||||
public get initialScrollProgress(): number { return this._initialScrollProgress; }
|
||||
public set initialScrollProgress(value: number) {
|
||||
this._initialScrollProgress = value;
|
||||
this.withWebview(webview => webview.initialScrollProgress = value);
|
||||
}
|
||||
|
||||
public get state(): string | undefined { return this._state; }
|
||||
public set state(value: string | undefined) {
|
||||
this._state = value;
|
||||
this.withWebview(webview => webview.state = value);
|
||||
}
|
||||
|
||||
public get contentOptions(): WebviewContentOptions { return this._contentOptions; }
|
||||
public set contentOptions(value: WebviewContentOptions) {
|
||||
this._contentOptions = value;
|
||||
this.withWebview(webview => webview.contentOptions = value);
|
||||
}
|
||||
|
||||
private readonly _onDidFocus = this._register(new Emitter<void>());
|
||||
public readonly onDidFocus: Event<void> = this._onDidFocus.event;
|
||||
|
||||
private readonly _onDidClickLink = this._register(new Emitter<URI>());
|
||||
public readonly onDidClickLink: Event<URI> = this._onDidClickLink.event;
|
||||
|
||||
private readonly _onDidScroll = this._register(new Emitter<{ scrollYPercentage: number; }>());
|
||||
public readonly onDidScroll: Event<{ scrollYPercentage: number; }> = this._onDidScroll.event;
|
||||
|
||||
private readonly _onDidUpdateState = this._register(new Emitter<string | undefined>());
|
||||
public readonly onDidUpdateState: Event<string | undefined> = this._onDidUpdateState.event;
|
||||
|
||||
private readonly _onMessage = this._register(new Emitter<any>());
|
||||
public readonly onMessage: Event<any> = this._onMessage.event;
|
||||
|
||||
sendMessage(data: any): void {
|
||||
if (this._webview.value) {
|
||||
this._webview.value.sendMessage(data);
|
||||
} else {
|
||||
this._pendingMessages.add(data);
|
||||
}
|
||||
}
|
||||
|
||||
update(html: string, options: WebviewContentOptions, retainContextWhenHidden: boolean): void {
|
||||
this._contentOptions = options;
|
||||
this._html = html;
|
||||
this.withWebview(webview => {
|
||||
webview.update(html, options, retainContextWhenHidden);
|
||||
});
|
||||
}
|
||||
|
||||
layout(): void { this.withWebview(webview => webview.layout()); }
|
||||
focus(): void { this.withWebview(webview => webview.focus()); }
|
||||
reload(): void { this.withWebview(webview => webview.reload()); }
|
||||
showFind(): void { this.withWebview(webview => webview.showFind()); }
|
||||
hideFind(): void { this.withWebview(webview => webview.hideFind()); }
|
||||
|
||||
public getInnerWebview() {
|
||||
return this._webview.value;
|
||||
}
|
||||
|
||||
private withWebview(f: (webview: Webview) => void): void {
|
||||
if (this._webview.value) {
|
||||
f(this._webview.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,9 @@ export class IFrameWebview extends Disposable implements Webview {
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
if (typeof environmentService.webviewEndpoint !== 'string') {
|
||||
const useExternalEndpoint = this._configurationService.getValue<string>('webview.experimental.useExternalEndpoint');
|
||||
|
||||
if (typeof environmentService.webviewEndpoint !== 'string' && !useExternalEndpoint) {
|
||||
throw new Error('To use iframe based webviews, you must configure `environmentService.webviewEndpoint`');
|
||||
}
|
||||
|
||||
@@ -142,7 +144,9 @@ export class IFrameWebview extends Disposable implements Webview {
|
||||
}
|
||||
|
||||
private get endpoint(): string {
|
||||
const endpoint = this.environmentService.webviewEndpoint!.replace('{{uuid}}', this.id);
|
||||
const useExternalEndpoint = this._configurationService.getValue<string>('webview.experimental.useExternalEndpoint');
|
||||
const baseEndpoint = useExternalEndpoint ? 'https://{{uuid}}.vscode-webview-test.com/8fa811108f0f0524c473020ef57b6620f6c201e1' : this.environmentService.webviewEndpoint!;
|
||||
const endpoint = baseEndpoint.replace('{{uuid}}', this.id);
|
||||
if (endpoint[endpoint.length - 1] === '/') {
|
||||
return endpoint.slice(0, endpoint.length - 1);
|
||||
}
|
||||
|
||||
@@ -3,14 +3,10 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IFrameWebview } from 'vs/workbench/contrib/webview/browser/webviewElement';
|
||||
import { IWebviewService, Webview, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/common/webview';
|
||||
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/common/webview';
|
||||
import { DynamicWebviewEditorOverlay } from './dynamicWebviewEditorOverlay';
|
||||
|
||||
export class WebviewService implements IWebviewService {
|
||||
_serviceBrand: any;
|
||||
@@ -35,166 +31,3 @@ export class WebviewService implements IWebviewService {
|
||||
return this._instantiationService.createInstance(DynamicWebviewEditorOverlay, id, options, contentOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Webview editor overlay that creates and destroys the underlying webview as needed.
|
||||
*/
|
||||
class DynamicWebviewEditorOverlay extends Disposable implements WebviewEditorOverlay {
|
||||
|
||||
private readonly _pendingMessages = new Set<any>();
|
||||
private readonly _webview = this._register(new MutableDisposable<WebviewElement>());
|
||||
private readonly _webviewEvents = this._register(new DisposableStore());
|
||||
|
||||
private _html: string = '';
|
||||
private _initialScrollProgress: number = 0;
|
||||
private _state: string | undefined = undefined;
|
||||
private _owner: any = undefined;
|
||||
|
||||
public constructor(
|
||||
private readonly id: string,
|
||||
public readonly options: WebviewOptions,
|
||||
private _contentOptions: WebviewContentOptions,
|
||||
@IWorkbenchLayoutService private readonly _layoutService: IWorkbenchLayoutService,
|
||||
@IWebviewService private readonly _webviewService: IWebviewService,
|
||||
) {
|
||||
super();
|
||||
|
||||
this._register(toDisposable(() => this.container.remove()));
|
||||
}
|
||||
|
||||
@memoize
|
||||
public get container() {
|
||||
const container = document.createElement('div');
|
||||
container.id = `webview-${this.id}`;
|
||||
this._layoutService.getContainer(Parts.EDITOR_PART).appendChild(container);
|
||||
return container;
|
||||
}
|
||||
|
||||
public claim(owner: any) {
|
||||
this._owner = owner;
|
||||
this.show();
|
||||
}
|
||||
|
||||
public release(owner: any) {
|
||||
if (this._owner !== owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._owner = undefined;
|
||||
this.container.style.visibility = 'hidden';
|
||||
if (!this.options.retainContextWhenHidden) {
|
||||
this._webview.clear();
|
||||
this._webviewEvents.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private show() {
|
||||
if (!this._webview.value) {
|
||||
const webview = this._webviewService.createWebview(this.id, this.options, this._contentOptions);
|
||||
this._webview.value = webview;
|
||||
webview.state = this._state;
|
||||
webview.html = this._html;
|
||||
|
||||
if (this.options.tryRestoreScrollPosition) {
|
||||
webview.initialScrollProgress = this._initialScrollProgress;
|
||||
}
|
||||
|
||||
this._webview.value.mountTo(this.container);
|
||||
|
||||
this._webviewEvents.clear();
|
||||
|
||||
webview.onDidFocus(() => {
|
||||
this._onDidFocus.fire();
|
||||
}, undefined, this._webviewEvents);
|
||||
|
||||
webview.onDidClickLink(x => {
|
||||
this._onDidClickLink.fire(x);
|
||||
}, undefined, this._webviewEvents);
|
||||
|
||||
webview.onDidScroll(x => {
|
||||
this._initialScrollProgress = x.scrollYPercentage;
|
||||
this._onDidScroll.fire(x);
|
||||
}, undefined, this._webviewEvents);
|
||||
|
||||
webview.onDidUpdateState(state => {
|
||||
this._state = state;
|
||||
this._onDidUpdateState.fire(state);
|
||||
}, undefined, this._webviewEvents);
|
||||
|
||||
webview.onMessage(x => {
|
||||
this._onMessage.fire(x);
|
||||
}, undefined, this._webviewEvents);
|
||||
|
||||
this._pendingMessages.forEach(msg => webview.sendMessage(msg));
|
||||
this._pendingMessages.clear();
|
||||
}
|
||||
this.container.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
public get html(): string { return this._html; }
|
||||
public set html(value: string) {
|
||||
this._html = value;
|
||||
this.withWebview(webview => webview.html = value);
|
||||
}
|
||||
|
||||
public get initialScrollProgress(): number { return this._initialScrollProgress; }
|
||||
public set initialScrollProgress(value: number) {
|
||||
this._initialScrollProgress = value;
|
||||
this.withWebview(webview => webview.initialScrollProgress = value);
|
||||
}
|
||||
|
||||
public get state(): string | undefined { return this._state; }
|
||||
public set state(value: string | undefined) {
|
||||
this._state = value;
|
||||
this.withWebview(webview => webview.state = value);
|
||||
}
|
||||
|
||||
public get contentOptions(): WebviewContentOptions { return this._contentOptions; }
|
||||
public set contentOptions(value: WebviewContentOptions) {
|
||||
this._contentOptions = value;
|
||||
this.withWebview(webview => webview.contentOptions = value);
|
||||
}
|
||||
|
||||
private readonly _onDidFocus = this._register(new Emitter<void>());
|
||||
public readonly onDidFocus: Event<void> = this._onDidFocus.event;
|
||||
|
||||
private readonly _onDidClickLink = this._register(new Emitter<URI>());
|
||||
public readonly onDidClickLink: Event<URI> = this._onDidClickLink.event;
|
||||
|
||||
private readonly _onDidScroll = this._register(new Emitter<{ scrollYPercentage: number; }>());
|
||||
public readonly onDidScroll: Event<{ scrollYPercentage: number; }> = this._onDidScroll.event;
|
||||
|
||||
private readonly _onDidUpdateState = this._register(new Emitter<string | undefined>());
|
||||
public readonly onDidUpdateState: Event<string | undefined> = this._onDidUpdateState.event;
|
||||
|
||||
private readonly _onMessage = this._register(new Emitter<any>());
|
||||
public readonly onMessage: Event<any> = this._onMessage.event;
|
||||
|
||||
sendMessage(data: any): void {
|
||||
if (this._webview.value) {
|
||||
this._webview.value.sendMessage(data);
|
||||
} else {
|
||||
this._pendingMessages.add(data);
|
||||
}
|
||||
}
|
||||
|
||||
update(html: string, options: WebviewContentOptions, retainContextWhenHidden: boolean): void {
|
||||
this._contentOptions = options;
|
||||
this._html = html;
|
||||
this.withWebview(webview => {
|
||||
webview.update(html, options, retainContextWhenHidden);
|
||||
});
|
||||
}
|
||||
|
||||
layout(): void { this.withWebview(webview => webview.layout()); }
|
||||
focus(): void { this.withWebview(webview => webview.focus()); }
|
||||
reload(): void { this.withWebview(webview => webview.reload()); }
|
||||
showFind(): void { this.withWebview(webview => webview.showFind()); }
|
||||
hideFind(): void { this.withWebview(webview => webview.hideFind()); }
|
||||
|
||||
private withWebview(f: (webview: Webview) => void): void {
|
||||
if (this._webview.value) {
|
||||
f(this._webview.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,8 @@ export interface WebviewEditorOverlay extends Webview {
|
||||
|
||||
claim(owner: any): void;
|
||||
release(owner: any): void;
|
||||
|
||||
getInnerWebview(): Webview | undefined;
|
||||
}
|
||||
|
||||
export const webviewDeveloperCategory = nls.localize('developer', "Developer");
|
||||
|
||||
@@ -15,9 +15,9 @@ import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/wor
|
||||
import { WebviewEditor } from 'vs/workbench/contrib/webview/browser/webviewEditor';
|
||||
import { IWebviewService, webviewDeveloperCategory } from 'vs/workbench/contrib/webview/common/webview';
|
||||
import * as webviewCommands from 'vs/workbench/contrib/webview/electron-browser/webviewCommands';
|
||||
import { WebviewService } from 'vs/workbench/contrib/webview/electron-browser/webviewService';
|
||||
import { ElectronWebviewService } from 'vs/workbench/contrib/webview/electron-browser/webviewService';
|
||||
|
||||
registerSingleton(IWebviewService, WebviewService, true);
|
||||
registerSingleton(IWebviewService, ElectronWebviewService, true);
|
||||
|
||||
const actionRegistry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Command, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { WebviewEditor } from 'vs/workbench/contrib/webview/browser/webviewEditor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ElectronWebviewBasedWebview } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
|
||||
import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/common/webview';
|
||||
|
||||
export class OpenWebviewDeveloperToolsAction extends Action {
|
||||
static readonly ID = 'workbench.action.webview.openDeveloperTools';
|
||||
@@ -92,6 +93,11 @@ function withActiveWebviewBasedWebview(accessor: ServicesAccessor, f: (webview:
|
||||
webViewEditor.withWebview(webview => {
|
||||
if (webview instanceof ElectronWebviewBasedWebview) {
|
||||
f(webview);
|
||||
} else if ((webview as WebviewEditorOverlay).getInnerWebview) {
|
||||
const innerWebview = (webview as WebviewEditorOverlay).getInnerWebview();
|
||||
if (innerWebview instanceof ElectronWebviewBasedWebview) {
|
||||
f(innerWebview);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,25 +3,39 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { WebviewService as BrowserWebviewService } from 'vs/workbench/contrib/webview/browser/webviewService';
|
||||
import { IWebviewService, WebviewContentOptions, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/common/webview';
|
||||
import { DynamicWebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/dynamicWebviewEditorOverlay';
|
||||
import { IFrameWebview } from 'vs/workbench/contrib/webview/browser/webviewElement';
|
||||
import { IWebviewService, WebviewContentOptions, WebviewEditorOverlay, WebviewElement, WebviewOptions } from 'vs/workbench/contrib/webview/common/webview';
|
||||
import { ElectronWebviewBasedWebview } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
|
||||
|
||||
export class WebviewService extends BrowserWebviewService implements IWebviewService {
|
||||
export class ElectronWebviewService implements IWebviewService {
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
) {
|
||||
super(instantiationService);
|
||||
}
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IConfigurationService private readonly _configService: IConfigurationService,
|
||||
) { }
|
||||
|
||||
createWebview(
|
||||
_id: string,
|
||||
id: string,
|
||||
options: WebviewOptions,
|
||||
contentOptions: WebviewContentOptions
|
||||
): WebviewElement {
|
||||
return this.instantiationService.createInstance(ElectronWebviewBasedWebview, options, contentOptions);
|
||||
const useExternalEndpoint = this._configService.getValue<string>('webview.experimental.useExternalEndpoint');
|
||||
if (useExternalEndpoint) {
|
||||
return this._instantiationService.createInstance(IFrameWebview, id, options, contentOptions);
|
||||
} else {
|
||||
return this._instantiationService.createInstance(ElectronWebviewBasedWebview, options, contentOptions);
|
||||
}
|
||||
}
|
||||
|
||||
createWebviewEditorOverlay(
|
||||
id: string,
|
||||
options: WebviewOptions,
|
||||
contentOptions: WebviewContentOptions,
|
||||
): WebviewEditorOverlay {
|
||||
return this._instantiationService.createInstance(DynamicWebviewEditorOverlay, id, options, contentOptions);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user