Skip to content

Commit 3bb6bc5

Browse files
committed
Add basic support for saving untitled custom editors
1 parent 42761b9 commit 3bb6bc5

1 file changed

Lines changed: 31 additions & 6 deletions

File tree

src/vs/workbench/api/browser/mainThreadWebview.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55

66
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
77
import { CancellationToken } from 'vs/base/common/cancellation';
8-
import { onUnexpectedError, isPromiseCanceledError } from 'vs/base/common/errors';
8+
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
99
import { Emitter, Event } from 'vs/base/common/event';
1010
import { Disposable, DisposableStore, dispose, IDisposable, IReference } from 'vs/base/common/lifecycle';
1111
import { Schemas } from 'vs/base/common/network';
1212
import { basename } from 'vs/base/common/path';
1313
import { isWeb } from 'vs/base/common/platform';
14-
import { isEqual, isEqualOrParent } from 'vs/base/common/resources';
14+
import { isEqual, isEqualOrParent, toLocalResource } from 'vs/base/common/resources';
1515
import { escape } from 'vs/base/common/strings';
1616
import { URI, UriComponents } from 'vs/base/common/uri';
1717
import * as modes from 'vs/editor/common/modes';
1818
import { localize } from 'vs/nls';
19+
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
1920
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
2021
import { IFileService } from 'vs/platform/files/common/files';
2122
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -38,6 +39,7 @@ import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOption
3839
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
3940
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
4041
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
42+
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
4143
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
4244
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
4345
import { IWorkingCopy, IWorkingCopyBackup, IWorkingCopyService, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService';
@@ -661,10 +663,12 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
661663
fromBackup: boolean,
662664
private readonly _editable: boolean,
663665
private readonly _getEditors: () => CustomEditorInput[],
664-
@IWorkingCopyService workingCopyService: IWorkingCopyService,
665-
@ILabelService private readonly _labelService: ILabelService,
666+
@IFileDialogService private readonly _fileDialogService: IFileDialogService,
666667
@IFileService private readonly _fileService: IFileService,
668+
@ILabelService private readonly _labelService: ILabelService,
667669
@IUndoRedoService private readonly _undoService: IUndoRedoService,
670+
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
671+
@IWorkingCopyService workingCopyService: IWorkingCopyService,
668672
) {
669673
super();
670674

@@ -845,11 +849,20 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
845849
return !!await this.saveCustomEditor(options);
846850
}
847851

848-
public async saveCustomEditor(_options?: ISaveOptions): Promise<URI | undefined> {
852+
public async saveCustomEditor(options?: ISaveOptions): Promise<URI | undefined> {
849853
if (!this._editable) {
850854
return undefined;
851855
}
852-
// TODO: handle save untitled case
856+
857+
if (this._editorResource.scheme === Schemas.untitled) {
858+
const targetUri = await this.suggestUntitledSavePath(options);
859+
if (!targetUri) {
860+
return undefined;
861+
}
862+
863+
await this.saveCustomEditorAs(this._editorResource, targetUri, options);
864+
return targetUri;
865+
}
853866

854867
const savePromise = createCancelablePromise(token => this._proxy.$onSave(this._editorResource, this.viewType, token));
855868
this._ongoingSave?.cancel();
@@ -871,6 +884,18 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
871884
return this._editorResource;
872885
}
873886

887+
private suggestUntitledSavePath(options: ISaveOptions | undefined): Promise<URI | undefined> {
888+
if (this._editorResource.scheme !== Schemas.untitled) {
889+
throw new Error('Resource is not untitled');
890+
}
891+
892+
const remoteAuthority = this._environmentService.configuration.remoteAuthority;
893+
const localResrouce = toLocalResource(this._editorResource, remoteAuthority);
894+
895+
896+
return this._fileDialogService.pickFileToSave(localResrouce, options?.availableFileSystems);
897+
}
898+
874899
public async saveCustomEditorAs(resource: URI, targetResource: URI, _options?: ISaveOptions): Promise<boolean> {
875900
if (this._editable) {
876901
// TODO: handle cancellation

0 commit comments

Comments
 (0)