diff --git a/src/vs/workbench/api/browser/mainThreadWebview.ts b/src/vs/workbench/api/browser/mainThreadWebview.ts index 332017e9ee0..70f129c7a70 100644 --- a/src/vs/workbench/api/browser/mainThreadWebview.ts +++ b/src/vs/workbench/api/browser/mainThreadWebview.ts @@ -279,12 +279,12 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma this._revivers.delete(viewType); } - public $registerTextEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void { - return this.registerEditorProvider(ModelType.Text, extensionData, viewType, options); + public $registerTextEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: extHostProtocol.CustomTextEditorCapabilities): void { + this.registerEditorProvider(ModelType.Text, extensionData, viewType, options, capabilities); } public $registerCustomEditorProvider(extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void { - return this.registerEditorProvider(ModelType.Custom, extensionData, viewType, options); + this.registerEditorProvider(ModelType.Custom, extensionData, viewType, options, {}); } private registerEditorProvider( @@ -292,41 +292,45 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma extensionData: extHostProtocol.WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, - ): void { + capabilities: extHostProtocol.CustomTextEditorCapabilities, + ): DisposableStore { if (this._editorProviders.has(viewType)) { throw new Error(`Provider for ${viewType} already registered`); } const extension = reviveWebviewExtension(extensionData); - this._editorProviders.set(viewType, this._webviewWorkbenchService.registerResolver({ + const disposables = new DisposableStore(); + disposables.add(this._webviewWorkbenchService.registerResolver({ canResolve: (webviewInput) => { return webviewInput instanceof CustomEditorInput && webviewInput.viewType === viewType; }, resolveWebview: async (webviewInput: CustomEditorInput) => { const handle = webviewInput.id; this._webviewInputs.add(handle, webviewInput); - this.hookupWebviewEventDelegate(handle, webviewInput); + this.hookupWebviewEventDelegate(handle, webviewInput); webviewInput.webview.options = options; webviewInput.webview.extension = extension; const resource = webviewInput.resource; + let modelRef = await this.getOrCreateCustomEditorModel(modelType, resource, viewType); - const modelRef = await this.getOrCreateCustomEditorModel(modelType, webviewInput, resource, viewType); webviewInput.webview.onDispose(() => { modelRef.dispose(); }); + if (capabilities.supportsMove) { + webviewInput.onMove(async (newResource: URI) => { + const oldModel = modelRef; + modelRef = await this.getOrCreateCustomEditorModel(modelType, newResource, viewType); + this._proxy.$onMoveCustomEditor(handle, newResource, viewType); + oldModel.dispose(); + }); + } + try { - await this._proxy.$resolveWebviewEditor( - resource, - handle, - viewType, - webviewInput.getTitle(), - editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0), - webviewInput.webview.options - ); + await this._proxy.$resolveWebviewEditor(resource, handle, viewType, webviewInput.getTitle(), editorGroupToViewColumn(this._editorGroupService, webviewInput.group || 0), webviewInput.webview.options); } catch (error) { onUnexpectedError(error); webviewInput.webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType); @@ -334,6 +338,10 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma } } })); + + this._editorProviders.set(viewType, disposables); + + return disposables; } public $unregisterEditorProvider(viewType: string): void { @@ -350,11 +358,10 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma private async getOrCreateCustomEditorModel( modelType: ModelType, - webviewInput: WebviewInput, resource: URI, viewType: string, ): Promise> { - const existingModel = this._customEditorService.models.tryRetain(webviewInput.resource, webviewInput.viewType); + const existingModel = this._customEditorService.models.tryRetain(resource, viewType); if (existingModel) { return existingModel; } @@ -612,6 +619,10 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod //#endregion + public isReadonly() { + return this._editable; + } + public get viewType() { return this._viewType; } diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index 8effe6aab9e..8073a67f522 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -97,7 +97,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { } public isReadonly(): boolean { - return false; // TODO + return this._modelRef ? this._modelRef.object.isReadonly() : false; } public isDirty(): boolean { diff --git a/src/vs/workbench/contrib/customEditor/common/customEditor.ts b/src/vs/workbench/contrib/customEditor/common/customEditor.ts index 3bfb81c05e5..5893a51979d 100644 --- a/src/vs/workbench/contrib/customEditor/common/customEditor.ts +++ b/src/vs/workbench/contrib/customEditor/common/customEditor.ts @@ -49,6 +49,8 @@ export interface ICustomEditorModel extends IDisposable { readonly viewType: string; readonly resource: URI; + isReadonly(): boolean; + isDirty(): boolean; readonly onDidChangeDirty: Event; diff --git a/src/vs/workbench/contrib/customEditor/common/customTextEditorModel.ts b/src/vs/workbench/contrib/customEditor/common/customTextEditorModel.ts index a1d8019684d..a041fa249df 100644 --- a/src/vs/workbench/contrib/customEditor/common/customTextEditorModel.ts +++ b/src/vs/workbench/contrib/customEditor/common/customTextEditorModel.ts @@ -31,12 +31,12 @@ export class CustomTextEditorModel extends Disposable implements ICustomEditorMo private constructor( public readonly viewType: string, private readonly _resource: URI, - model: IReference, + private readonly _model: IReference, @ITextFileService private readonly textFileService: ITextFileService, ) { super(); - this._register(model); + this._register(_model); this._register(this.textFileService.files.onDidChangeDirty(e => { if (isEqual(this.resource, e.resource)) { @@ -50,6 +50,10 @@ export class CustomTextEditorModel extends Disposable implements ICustomEditorMo return this._resource; } + public isReadonly(): boolean { + return this._model.object.isReadonly(); + } + public isDirty(): boolean { return this.textFileService.isDirty(this.resource); }