Skip to content

Commit

Permalink
Move webview content state into webviewPanel instead of webviewEditor
Browse files Browse the repository at this point in the history
Split out from #77131

The current webview editor api is very procedural. This model has some problems when it comes to supporting editing resources, but actually does make a lot of sense for webviews that aren't backed by real file system resources. For example, if you have a webview that edits some document in the cloud, you should not be required to implement a custom file system provider just to enable basic saving.

This change moves the `onWillSave` and `webviewEditorState` properties back onto `WebviewPanel` instead of keeping them specific to `WebviewEditor`. The save implementation does not fully work yet, as the will require #81521
  • Loading branch information
mjbvz committed Sep 27, 2019
1 parent e5efdb4 commit e0762af
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/vs/editor/common/modes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,7 @@ export interface IWebviewPanelOptions {
/**
* @internal
*/
export const enum WebviewEditorState {
export const enum WebviewContentState {
Readonly = 1,
Unchanged = 2,
Dirty = 3,
Expand Down
25 changes: 17 additions & 8 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1085,30 +1085,34 @@ declare module 'vscode' {

//#region Custom editors, mjbvz

export enum WebviewEditorState {
export enum WebviewContentState {
/**
* The webview editor's content cannot be modified.
* The webview content cannot be modified.
*
* This disables save
* This disables save.
*/
Readonly = 1,

/**
* The webview editor's content has not been changed but they can be modified and saved.
* The webview content has not been changed but they can be modified and saved.
*/
Unchanged = 2,

/**
* The webview editor's content has been changed and can be saved.
* The webview content has been changed and can be saved.
*/
Dirty = 3,
}

export interface WebviewEditor extends WebviewPanel {
state: WebviewEditorState;
export interface WebviewEditorState {
readonly contentState: WebviewContentState;
}

export interface WebviewPanel {
editorState: WebviewEditorState;

/**
* Fired when the webview editor is saved.
* Fired when the webview is being saved.
*
* Both `Unchanged` and `Dirty` editors can be saved.
*
Expand All @@ -1117,6 +1121,11 @@ declare module 'vscode' {
readonly onWillSave: Event<{ waitUntil: (thenable: Thenable<boolean>) => void }>;
}

export interface WebviewEditor extends WebviewPanel {
// TODO: We likely do not want `editorState` and `onWillSave` enabled for
// resource backed webviews
}

export interface WebviewEditorProvider {
/**
* Fills out a `WebviewEditor` for a given resource.
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/browser/mainThreadWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export class MainThreadWebviews extends Disposable implements MainThreadWebviews
webview.setName(value);
}

public $setState(handle: WebviewPanelHandle, state: modes.WebviewEditorState): void {
public $setState(handle: WebviewPanelHandle, state: modes.WebviewContentState): void {
const webview = this.getWebviewEditorInput(handle);
if (webview instanceof CustomFileEditorInput) {
webview.setState(state);
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
CallHierarchyItem: extHostTypes.CallHierarchyItem,
DebugConsoleMode: extHostTypes.DebugConsoleMode,
Decoration: extHostTypes.Decoration,
WebviewEditorState: extHostTypes.WebviewEditorState,
WebviewContentState: extHostTypes.WebviewContentState,
UIKind: UIKind
};
};
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,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;
$setState(handle: WebviewPanelHandle, state: modes.WebviewContentState): void;
$setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void;

$setHtml(handle: WebviewPanelHandle, value: string): void;
Expand Down
12 changes: 6 additions & 6 deletions src/vs/workbench/api/common/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1163,13 +1163,13 @@ export namespace LogLevel {
return types.LogLevel.Info;
}
}
export namespace WebviewEditorState {
export function from(state: vscode.WebviewEditorState): modes.WebviewEditorState {
export namespace WebviewContentState {
export function from(state: vscode.WebviewContentState): modes.WebviewContentState {
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');
case types.WebviewContentState.Readonly: return modes.WebviewContentState.Readonly;
case types.WebviewContentState.Unchanged: return modes.WebviewContentState.Unchanged;
case types.WebviewContentState.Dirty: return modes.WebviewContentState.Dirty;
default: throw new Error('Unknown vscode.WebviewContentState');
}
}
}
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHostTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2399,7 +2399,7 @@ export class Decoration {
bubble?: boolean;
}

export enum WebviewEditorState {
export enum WebviewContentState {
Readonly = 1,
Unchanged = 2,
Dirty = 3,
Expand Down
13 changes: 7 additions & 6 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, WebviewEditorState } from './extHostTypes';
import { Disposable, WebviewContentState } from './extHostTypes';

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

Expand Down Expand Up @@ -93,7 +93,9 @@ export class ExtHostWebviewEditor implements vscode.WebviewEditor {
private _viewColumn: vscode.ViewColumn | undefined;
private _visible: boolean = true;
private _active: boolean = true;
private _state = WebviewEditorState.Readonly;
private _state: vscode.WebviewEditorState = {
contentState: WebviewContentState.Readonly,
};

_isDisposed: boolean = false;

Expand All @@ -103,7 +105,6 @@ export class ExtHostWebviewEditor implements vscode.WebviewEditor {
readonly _onDidChangeViewStateEmitter = new Emitter<vscode.WebviewPanelOnDidChangeViewStateEvent>();
public readonly onDidChangeViewState: Event<vscode.WebviewPanelOnDidChangeViewStateEvent> = this._onDidChangeViewStateEmitter.event;


constructor(
handle: WebviewPanelHandle,
proxy: MainThreadWebviewsShape,
Expand Down Expand Up @@ -214,13 +215,13 @@ export class ExtHostWebviewEditor implements vscode.WebviewEditor {
this._visible = value;
}

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

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

private readonly _onWillSave = new Emitter<{ waitUntil: (thenable: Thenable<boolean>) => void }>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Emitter } from 'vs/base/common/event';
import { UnownedDisposable } from 'vs/base/common/lifecycle';
import { basename } from 'vs/base/common/path';
import { URI } from 'vs/base/common/uri';
import { WebviewEditorState } from 'vs/editor/common/modes';
import { WebviewContentState } from 'vs/editor/common/modes';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { ILabelService } from 'vs/platform/label/common/label';
Expand All @@ -26,7 +26,7 @@ export class CustomFileEditorInput extends WebviewInput {
private name?: string;
private _hasResolved = false;
private readonly _editorResource: URI;
private _state = WebviewEditorState.Readonly;
private _state = WebviewContentState.Readonly;

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

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

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

public async confirmSave(): Promise<ConfirmResult> {
Expand Down

0 comments on commit e0762af

Please sign in to comment.