Hook up very basic undo/redo for webview editors

For #77131
This commit is contained in:
Matt Bierner
2019-11-15 17:42:56 -08:00
parent ba19fe0e9b
commit 27a33ee6fe
11 changed files with 191 additions and 48 deletions

View File

@@ -12,7 +12,6 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import * as modes from 'vs/editor/common/modes';
import { localize } from 'vs/nls';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IProductService } from 'vs/platform/product/common/productService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -21,7 +20,7 @@ import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } fr
import { IEditorInput } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
import { CustomEditorModel } from 'vs/workbench/contrib/customEditor/common/customEditorModel';
import { ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
@@ -96,14 +95,13 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
private readonly _webviewInputs = new WebviewInputStore();
private readonly _revivers = new Map<string, IDisposable>();
private readonly _editorProviders = new Map<string, IDisposable>();
private readonly _models = new Map<string, CustomEditorModel>();
constructor(
context: extHostProtocol.IExtHostContext,
@IExtensionService extensionService: IExtensionService,
@ICustomEditorService private readonly _customEditorService: ICustomEditorService,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
@IEditorService private readonly _editorService: IEditorService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IOpenerService private readonly _openerService: IOpenerService,
@IProductService private readonly _productService: IProductService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@@ -273,18 +271,20 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
webviewInput.webview.options = options;
webviewInput.webview.extension = extension;
const model = this._instantiationService.createInstance(CustomEditorModel, webviewInput.getResource());
webviewInput.setModel(model);
this._models.set(handle, model);
webviewInput.onDispose(() => {
this._models.delete(handle);
});
const model = await this._customEditorService.models.loadOrCreate(webviewInput.getResource(), webviewInput.viewType);
model.onUndo(edit => {
this._proxy.$undoEdits(handle, [edit]);
});
model.onRedo(edit => {
this._proxy.$redoEdits(handle, [edit]);
});
webviewInput.onDispose(() => {
this._customEditorService.models.disposeModel(model);
});
try {
await this._proxy.$resolveWebviewEditor(
webviewInput.getResource(),
@@ -318,7 +318,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
throw new Error('Webview is not a webview editor');
}
const model = this._models.get(handle);
const model = this._customEditorService.models.get(webview.getResource(), webview.viewType);
if (!model) {
throw new Error('Could not find model for webview editor');
}

View File

@@ -590,6 +590,7 @@ export interface ExtHostWebviewsShape {
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
$resolveWebviewEditor(resource: UriComponents, newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
$undoEdits(handle: WebviewPanelHandle, edits: string[]): void;
$redoEdits(handle: WebviewPanelHandle, edits: string[]): void;
}
export interface MainThreadUrlsShape extends IDisposable {

View File

@@ -252,6 +252,10 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
assertIsDefined(this._capabilities).editingCapability?.undoEdits(edits);
}
_redoEdits(edits: string[]): void {
assertIsDefined(this._capabilities).editingCapability?.applyEdits(edits);
}
private assertNotDisposed() {
if (this._isDisposed) {
throw new Error('Webview is disposed');
@@ -447,6 +451,14 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
panel._undoEdits(edits);
}
$redoEdits(handle: WebviewPanelHandle, edits: string[]): void {
const panel = this.getWebviewPanel(handle);
if (!panel) {
return;
}
panel._redoEdits(edits);
}
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined {
return this._webviewPanels.get(handle);
}