55
66import { CancelablePromise , createCancelablePromise } from 'vs/base/common/async' ;
77import { CancellationToken } from 'vs/base/common/cancellation' ;
8- import { onUnexpectedError , isPromiseCanceledError } from 'vs/base/common/errors' ;
8+ import { isPromiseCanceledError , onUnexpectedError } from 'vs/base/common/errors' ;
99import { Emitter , Event } from 'vs/base/common/event' ;
1010import { Disposable , DisposableStore , dispose , IDisposable , IReference } from 'vs/base/common/lifecycle' ;
1111import { Schemas } from 'vs/base/common/network' ;
1212import { basename } from 'vs/base/common/path' ;
1313import { 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' ;
1515import { escape } from 'vs/base/common/strings' ;
1616import { URI , UriComponents } from 'vs/base/common/uri' ;
1717import * as modes from 'vs/editor/common/modes' ;
1818import { localize } from 'vs/nls' ;
19+ import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs' ;
1920import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions' ;
2021import { IFileService } from 'vs/platform/files/common/files' ;
2122import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation' ;
@@ -38,6 +39,7 @@ import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOption
3839import { IBackupFileService } from 'vs/workbench/services/backup/common/backup' ;
3940import { IEditorGroup , IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService' ;
4041import { IEditorService } from 'vs/workbench/services/editor/common/editorService' ;
42+ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService' ;
4143import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions' ;
4244import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService' ;
4345import { 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