Skip to content

Commit

Permalink
Adding concept of a state for webview editors
Browse files Browse the repository at this point in the history
#77131

This information will be used to show the dirty indicator and also enable/disable save
  • Loading branch information
mjbvz committed Sep 12, 2019
1 parent feb3936 commit 7a219ab
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 9 deletions.
9 changes: 9 additions & 0 deletions src/vs/editor/common/modes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1402,6 +1402,15 @@ export interface IWebviewPanelOptions {
readonly retainContextWhenHidden?: boolean;
}

/**
* @internal
*/
export const enum WebviewEditorState {
Readonly = 1,
Unchanged = 2,
Dirty = 3,
}

export interface CodeLens {
range: IRange;
id?: string;
Expand Down
10 changes: 9 additions & 1 deletion src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,15 @@ declare module 'vscode' {

//#region Custom editors, mjbvz

export interface WebviewEditor extends WebviewPanel { }
export enum WebviewEditorState {
Readonly = 1,
Unchanged = 2,
Dirty = 3,
}

export interface WebviewEditor extends WebviewPanel {
state: WebviewEditorState;
}

export interface WebviewEditorProvider {
/**
Expand Down
8 changes: 8 additions & 0 deletions src/vs/workbench/api/browser/mainThreadWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { extHostNamedCustomer } from '../common/extHostCustomers';
import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';

/**
* Bi-directional map between webview handles and inputs.
Expand Down Expand Up @@ -149,6 +150,13 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
webview.setName(value);
}

public $setState(handle: WebviewPanelHandle, state: modes.WebviewEditorState): void {
const webview = this.getWebviewEditorInput(handle);
if (webview instanceof CustomFileEditorInput) {
webview.setState(state);
}
}

public $setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void {
const webview = this.getWebviewEditorInput(handle);
webview.iconPath = reviveWebviewIcon(value);
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
CallHierarchyOutgoingCall: extHostTypes.CallHierarchyOutgoingCall,
CallHierarchyIncomingCall: extHostTypes.CallHierarchyIncomingCall,
CallHierarchyItem: extHostTypes.CallHierarchyItem,
Decoration: extHostTypes.Decoration
Decoration: extHostTypes.Decoration,
WebviewEditorState: extHostTypes.WebviewEditorState,
};
};
}
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ export interface MainThreadWebviewsShape extends IDisposable {
$disposeWebview(handle: WebviewPanelHandle): void;
$reveal(handle: WebviewPanelHandle, showOptions: WebviewPanelShowOptions): void;
$setTitle(handle: WebviewPanelHandle, value: string): void;
$setState(handle: WebviewPanelHandle, state: modes.WebviewEditorState): void;
$setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void;

$setHtml(handle: WebviewPanelHandle, value: string): void;
Expand Down
10 changes: 10 additions & 0 deletions src/vs/workbench/api/common/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1163,3 +1163,13 @@ export namespace LogLevel {
return types.LogLevel.Info;
}
}
export namespace WebviewEditorState {
export function from(state: vscode.WebviewEditorState): modes.WebviewEditorState {
switch (state) {
case types.WebviewEditorState.Readonly: return modes.WebviewEditorState.Readonly;
case types.WebviewEditorState.Unchanged: return modes.WebviewEditorState.Unchanged;
case types.WebviewEditorState.Dirty: return modes.WebviewEditorState.Dirty;
default: throw new Error('Unknown vscode.WebviewEditorState');
}
}
}
6 changes: 6 additions & 0 deletions src/vs/workbench/api/common/extHostTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2382,3 +2382,9 @@ export class Decoration {
priority?: number;
bubble?: boolean;
}

export enum WebviewEditorState {
Readonly = 1,
Unchanged = 2,
Dirty = 3,
}
24 changes: 17 additions & 7 deletions src/vs/workbench/api/common/extHostWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
import * as vscode from 'vscode';
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewStateData } from './extHost.protocol';
import { Disposable } from './extHostTypes';
import { Disposable, WebviewEditorState } from './extHostTypes';

type IconPath = URI | { light: URI, dark: URI };

Expand Down Expand Up @@ -79,7 +79,7 @@ export class ExtHostWebview implements vscode.Webview {
}
}

export class ExtHostWebviewPanel implements vscode.WebviewPanel {
export class ExtHostWebviewEditor implements vscode.WebviewEditor {

private readonly _handle: WebviewPanelHandle;
private readonly _proxy: MainThreadWebviewsShape;
Expand All @@ -92,6 +92,7 @@ export class ExtHostWebviewPanel implements vscode.WebviewPanel {
private _viewColumn: vscode.ViewColumn | undefined;
private _visible: boolean = true;
private _active: boolean = true;
private _state = WebviewEditorState.Readonly;

_isDisposed: boolean = false;

Expand Down Expand Up @@ -212,6 +213,15 @@ export class ExtHostWebviewPanel implements vscode.WebviewPanel {
this._visible = value;
}

public get state(): vscode.WebviewEditorState {
return this._state;
}

public set state(newState: vscode.WebviewEditorState) {
this._state = newState;
this._proxy.$setState(this._handle, typeConverters.WebviewEditorState.from(newState));
}

public postMessage(message: any): Promise<boolean> {
this.assertNotDisposed();
return this._proxy.$postMessage(this._handle, message);
Expand Down Expand Up @@ -239,7 +249,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}

private readonly _proxy: MainThreadWebviewsShape;
private readonly _webviewPanels = new Map<WebviewPanelHandle, ExtHostWebviewPanel>();
private readonly _webviewPanels = new Map<WebviewPanelHandle, ExtHostWebviewEditor>();
private readonly _serializers = new Map<string, vscode.WebviewPanelSerializer>();
private readonly _editorProviders = new Map<string, vscode.WebviewEditorProvider>();

Expand Down Expand Up @@ -267,7 +277,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
this._proxy.$createWebviewPanel(handle, viewType, title, webviewShowOptions, convertWebviewOptions(options), extension.identifier, extension.extensionLocation);

const webview = new ExtHostWebview(handle, this._proxy, options, this.initData);
const panel = new ExtHostWebviewPanel(handle, this._proxy, viewType, title, viewColumn, options, webview);
const panel = new ExtHostWebviewEditor(handle, this._proxy, viewType, title, viewColumn, options, webview);
this._webviewPanels.set(handle, panel);
return panel;
}
Expand Down Expand Up @@ -381,12 +391,12 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}

const webview = new ExtHostWebview(webviewHandle, this._proxy, options, this.initData);
const revivedPanel = new ExtHostWebviewPanel(webviewHandle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
const revivedPanel = new ExtHostWebviewEditor(webviewHandle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
this._webviewPanels.set(webviewHandle, revivedPanel);
return Promise.resolve(serializer.deserializeWebviewPanel(revivedPanel, state));
}

private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewPanel | undefined {
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined {
return this._webviewPanels.get(handle);
}

Expand All @@ -405,7 +415,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}

const webview = new ExtHostWebview(webviewHandle, this._proxy, options, this.initData);
const revivedPanel = new ExtHostWebviewPanel(webviewHandle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
const revivedPanel = new ExtHostWebviewEditor(webviewHandle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
this._webviewPanels.set(webviewHandle, revivedPanel);
return Promise.resolve(provider.resolveWebviewEditor(URI.revive(resource), revivedPanel));
}
Expand Down
12 changes: 12 additions & 0 deletions src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@ import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webvi
import { WebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
import { IWebviewEditorService } from 'vs/workbench/contrib/webview/browser/webviewEditorService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { WebviewEditorState } from 'vs/editor/common/modes';

export class CustomFileEditorInput extends WebviewEditorInput {

public static typeId = 'workbench.editors.webviewEditor';

private name?: string;
private _hasResolved = false;
private readonly _editorResource: URI;
private _state = WebviewEditorState.Readonly;

constructor(
resource: URI,
Expand Down Expand Up @@ -94,4 +97,13 @@ export class CustomFileEditorInput extends WebviewEditorInput {
}
return super.resolve();
}

public setState(newState: WebviewEditorState): void {
this._state = newState;
this._onDidChangeDirty.fire();
}

public isDirty() {
return this._state === WebviewEditorState.Dirty;
}
}

0 comments on commit 7a219ab

Please sign in to comment.