@codingame/monaco-vscode-dialogs-service-override 4.1.0 → 4.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1039 @@
1
+ import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
2
+ import { localizeWithPath } from 'vscode/vscode/vs/nls';
3
+ import { basename, joinPath, toLocalResource, extname, dirname, extUriIgnorePathCase, relativePath, hasTrailingPathSeparator, addTrailingPathSeparator, isEqual, removeTrailingPathSeparator } from 'vscode/vscode/vs/base/common/resources';
4
+ import { deepClone } from 'vscode/vscode/vs/base/common/objects';
5
+ import { FileKind, IFileService } from 'vscode/vscode/vs/platform/files/common/files';
6
+ import { ItemActivation, IQuickInputService } from 'vscode/vscode/vs/platform/quickinput/common/quickInput';
7
+ import { URI } from 'vscode/vscode/vs/base/common/uri';
8
+ import { isWindows } from 'vscode/vscode/vs/base/common/platform';
9
+ import '../../../../../../../override/vs/platform/dialogs/common/dialogs.js';
10
+ import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label';
11
+ import { IWorkspaceContextService } from 'vscode/vscode/vs/platform/workspace/common/workspace';
12
+ import { INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification';
13
+ import { IModelService } from 'vscode/vscode/vs/editor/common/services/model';
14
+ import { ILanguageService } from 'vscode/vscode/vs/editor/common/languages/language';
15
+ import { getIconClasses } from 'vscode/vscode/vs/editor/common/services/getIconClasses';
16
+ import { Schemas } from 'vscode/vscode/vs/base/common/network';
17
+ import { IWorkbenchEnvironmentService } from 'vscode/vscode/vs/workbench/services/environment/common/environmentService';
18
+ import { IRemoteAgentService } from 'vscode/vscode/vs/workbench/services/remote/common/remoteAgentService';
19
+ import { RawContextKey, IContextKeyService } from 'vscode/vscode/vs/platform/contextkey/common/contextkey';
20
+ import { format, equalsIgnoreCase, startsWithIgnoreCase } from 'vscode/vscode/vs/base/common/strings';
21
+ import { IKeybindingService } from 'vscode/vscode/vs/platform/keybinding/common/keybinding';
22
+ import { isValidBasename } from 'vscode/vscode/vs/base/common/extpath';
23
+ import { Emitter } from 'vscode/vscode/vs/base/common/event';
24
+ import { dispose } from 'vscode/vscode/vs/base/common/lifecycle';
25
+ import { createCancelablePromise } from 'vscode/vscode/vs/base/common/async';
26
+ import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
27
+ import { normalizeDriveLetter } from 'vscode/vscode/vs/base/common/labels';
28
+ import { IPathService } from 'vscode/vscode/vs/workbench/services/path/common/pathService';
29
+ import { IAccessibilityService } from 'vscode/vscode/vs/platform/accessibility/common/accessibility';
30
+ import { getActiveDocument } from 'vscode/vscode/vs/base/browser/dom';
31
+ import { IFileDialogService } from 'vscode/vscode/vs/platform/dialogs/common/dialogs';
32
+
33
+ var OpenLocalFileCommand;
34
+ ( (function(OpenLocalFileCommand) {
35
+ OpenLocalFileCommand.ID = 'workbench.action.files.openLocalFile';
36
+ OpenLocalFileCommand.LABEL = ( localizeWithPath(
37
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
38
+ 'openLocalFile',
39
+ "Open Local File..."
40
+ ));
41
+ function handler() {
42
+ return accessor => {
43
+ const dialogService = accessor.get(IFileDialogService);
44
+ return dialogService.pickFileAndOpen({ forceNewWindow: false, availableFileSystems: [Schemas.file] });
45
+ };
46
+ }
47
+ OpenLocalFileCommand.handler = handler;
48
+ })(OpenLocalFileCommand || (OpenLocalFileCommand = {})));
49
+ var SaveLocalFileCommand;
50
+ ( (function(SaveLocalFileCommand) {
51
+ SaveLocalFileCommand.ID = 'workbench.action.files.saveLocalFile';
52
+ SaveLocalFileCommand.LABEL = ( localizeWithPath(
53
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
54
+ 'saveLocalFile',
55
+ "Save Local File..."
56
+ ));
57
+ function handler() {
58
+ return accessor => {
59
+ const editorService = accessor.get(IEditorService);
60
+ const activeEditorPane = editorService.activeEditorPane;
61
+ if (activeEditorPane) {
62
+ return editorService.save({ groupId: activeEditorPane.group.id, editor: activeEditorPane.input }, { saveAs: true, availableFileSystems: [Schemas.file], reason: 1 });
63
+ }
64
+ return Promise.resolve(undefined);
65
+ };
66
+ }
67
+ SaveLocalFileCommand.handler = handler;
68
+ })(SaveLocalFileCommand || (SaveLocalFileCommand = {})));
69
+ var OpenLocalFolderCommand;
70
+ ( (function(OpenLocalFolderCommand) {
71
+ OpenLocalFolderCommand.ID = 'workbench.action.files.openLocalFolder';
72
+ OpenLocalFolderCommand.LABEL = ( localizeWithPath(
73
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
74
+ 'openLocalFolder',
75
+ "Open Local Folder..."
76
+ ));
77
+ function handler() {
78
+ return accessor => {
79
+ const dialogService = accessor.get(IFileDialogService);
80
+ return dialogService.pickFolderAndOpen({ forceNewWindow: false, availableFileSystems: [Schemas.file] });
81
+ };
82
+ }
83
+ OpenLocalFolderCommand.handler = handler;
84
+ })(OpenLocalFolderCommand || (OpenLocalFolderCommand = {})));
85
+ var OpenLocalFileFolderCommand;
86
+ ( (function(OpenLocalFileFolderCommand) {
87
+ OpenLocalFileFolderCommand.ID = 'workbench.action.files.openLocalFileFolder';
88
+ OpenLocalFileFolderCommand.LABEL = ( localizeWithPath(
89
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
90
+ 'openLocalFileFolder',
91
+ "Open Local..."
92
+ ));
93
+ function handler() {
94
+ return accessor => {
95
+ const dialogService = accessor.get(IFileDialogService);
96
+ return dialogService.pickFileFolderAndOpen({ forceNewWindow: false, availableFileSystems: [Schemas.file] });
97
+ };
98
+ }
99
+ OpenLocalFileFolderCommand.handler = handler;
100
+ })(OpenLocalFileFolderCommand || (OpenLocalFileFolderCommand = {})));
101
+ var UpdateResult;
102
+ ( (function(UpdateResult) {
103
+ UpdateResult[UpdateResult["Updated"] = 0] = "Updated";
104
+ UpdateResult[UpdateResult["UpdatedWithTrailing"] = 1] = "UpdatedWithTrailing";
105
+ UpdateResult[UpdateResult["Updating"] = 2] = "Updating";
106
+ UpdateResult[UpdateResult["NotUpdated"] = 3] = "NotUpdated";
107
+ UpdateResult[UpdateResult["InvalidPath"] = 4] = "InvalidPath";
108
+ })(UpdateResult || (UpdateResult = {})));
109
+ const RemoteFileDialogContext = ( new RawContextKey('remoteFileDialogVisible', false));
110
+ let SimpleFileDialog = class SimpleFileDialog {
111
+ constructor(fileService, quickInputService, labelService, workspaceContextService, notificationService, fileDialogService, modelService, languageService, environmentService, remoteAgentService, pathService, keybindingService, contextKeyService, accessibilityService) {
112
+ this.fileService = fileService;
113
+ this.quickInputService = quickInputService;
114
+ this.labelService = labelService;
115
+ this.workspaceContextService = workspaceContextService;
116
+ this.notificationService = notificationService;
117
+ this.fileDialogService = fileDialogService;
118
+ this.modelService = modelService;
119
+ this.languageService = languageService;
120
+ this.environmentService = environmentService;
121
+ this.remoteAgentService = remoteAgentService;
122
+ this.pathService = pathService;
123
+ this.keybindingService = keybindingService;
124
+ this.accessibilityService = accessibilityService;
125
+ this.hidden = false;
126
+ this.allowFileSelection = true;
127
+ this.allowFolderSelection = false;
128
+ this.requiresTrailing = false;
129
+ this.userEnteredPathSegment = '';
130
+ this.autoCompletePathSegment = '';
131
+ this.isWindows = false;
132
+ this.separator = '/';
133
+ this.onBusyChangeEmitter = ( new Emitter());
134
+ this.disposables = [
135
+ this.onBusyChangeEmitter
136
+ ];
137
+ this.remoteAuthority = this.environmentService.remoteAuthority;
138
+ this.contextKey = RemoteFileDialogContext.bindTo(contextKeyService);
139
+ this.scheme = this.pathService.defaultUriScheme;
140
+ }
141
+ set busy(busy) {
142
+ if (this.filePickBox.busy !== busy) {
143
+ this.filePickBox.busy = busy;
144
+ this.onBusyChangeEmitter.fire(busy);
145
+ }
146
+ }
147
+ get busy() {
148
+ return this.filePickBox.busy;
149
+ }
150
+ async showOpenDialog(options = {}) {
151
+ this.scheme = this.getScheme(options.availableFileSystems, options.defaultUri);
152
+ this.userHome = await this.getUserHome();
153
+ this.trueHome = await this.getUserHome(true);
154
+ const newOptions = this.getOptions(options);
155
+ if (!newOptions) {
156
+ return Promise.resolve(undefined);
157
+ }
158
+ this.options = newOptions;
159
+ return this.pickResource();
160
+ }
161
+ async showSaveDialog(options) {
162
+ this.scheme = this.getScheme(options.availableFileSystems, options.defaultUri);
163
+ this.userHome = await this.getUserHome();
164
+ this.trueHome = await this.getUserHome(true);
165
+ this.requiresTrailing = true;
166
+ const newOptions = this.getOptions(options, true);
167
+ if (!newOptions) {
168
+ return Promise.resolve(undefined);
169
+ }
170
+ this.options = newOptions;
171
+ this.options.canSelectFolders = true;
172
+ this.options.canSelectFiles = true;
173
+ return ( new Promise((resolve) => {
174
+ this.pickResource(true).then(folderUri => {
175
+ resolve(folderUri);
176
+ });
177
+ }));
178
+ }
179
+ getOptions(options, isSave = false) {
180
+ let defaultUri = undefined;
181
+ let filename = undefined;
182
+ if (options.defaultUri) {
183
+ defaultUri = (this.scheme === options.defaultUri.scheme) ? options.defaultUri : undefined;
184
+ filename = isSave ? basename(options.defaultUri) : undefined;
185
+ }
186
+ if (!defaultUri) {
187
+ defaultUri = this.userHome;
188
+ if (filename) {
189
+ defaultUri = joinPath(defaultUri, filename);
190
+ }
191
+ }
192
+ if ((this.scheme !== Schemas.file) && !this.fileService.hasProvider(defaultUri)) {
193
+ this.notificationService.info(( localizeWithPath(
194
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
195
+ 'remoteFileDialog.notConnectedToRemote',
196
+ 'File system provider for {0} is not available.',
197
+ ( defaultUri.toString())
198
+ )));
199
+ return undefined;
200
+ }
201
+ const newOptions = deepClone(options);
202
+ newOptions.defaultUri = defaultUri;
203
+ return newOptions;
204
+ }
205
+ remoteUriFrom(path, hintUri) {
206
+ if (!path.startsWith('\\\\')) {
207
+ path = path.replace(/\\/g, '/');
208
+ }
209
+ const uri = this.scheme === Schemas.file ? URI.file(path) : ( URI.from(
210
+ { scheme: this.scheme, path, query: hintUri?.query, fragment: hintUri?.fragment }
211
+ ));
212
+ const authority = (uri.scheme === Schemas.file) ? undefined : (this.remoteAuthority ?? hintUri?.authority);
213
+ return toLocalResource(uri, authority,
214
+ authority ? this.pathService.defaultUriScheme : uri.scheme);
215
+ }
216
+ getScheme(available, defaultUri) {
217
+ if (available && available.length > 0) {
218
+ if (defaultUri && (available.indexOf(defaultUri.scheme) >= 0)) {
219
+ return defaultUri.scheme;
220
+ }
221
+ return available[0];
222
+ }
223
+ else if (defaultUri) {
224
+ return defaultUri.scheme;
225
+ }
226
+ return Schemas.file;
227
+ }
228
+ async getRemoteAgentEnvironment() {
229
+ if (this.remoteAgentEnvironment === undefined) {
230
+ this.remoteAgentEnvironment = await this.remoteAgentService.getEnvironment();
231
+ }
232
+ return this.remoteAgentEnvironment;
233
+ }
234
+ getUserHome(trueHome = false) {
235
+ return trueHome
236
+ ? this.pathService.userHome({ preferLocal: this.scheme === Schemas.file })
237
+ : this.fileDialogService.preferredHome(this.scheme);
238
+ }
239
+ async pickResource(isSave = false) {
240
+ this.allowFolderSelection = !!this.options.canSelectFolders;
241
+ this.allowFileSelection = !!this.options.canSelectFiles;
242
+ this.separator = this.labelService.getSeparator(this.scheme, this.remoteAuthority);
243
+ this.hidden = false;
244
+ this.isWindows = await this.checkIsWindowsOS();
245
+ let homedir = this.options.defaultUri ? this.options.defaultUri : this.workspaceContextService.getWorkspace().folders[0].uri;
246
+ let stat;
247
+ const ext = extname(homedir);
248
+ if (this.options.defaultUri) {
249
+ try {
250
+ stat = await this.fileService.stat(this.options.defaultUri);
251
+ }
252
+ catch (e) {
253
+ }
254
+ if (!stat || !stat.isDirectory) {
255
+ homedir = dirname(this.options.defaultUri);
256
+ this.trailing = basename(this.options.defaultUri);
257
+ }
258
+ }
259
+ return ( new Promise((resolve) => {
260
+ this.filePickBox = this.quickInputService.createQuickPick();
261
+ this.busy = true;
262
+ this.filePickBox.matchOnLabel = false;
263
+ this.filePickBox.sortByLabel = false;
264
+ this.filePickBox.ignoreFocusOut = true;
265
+ this.filePickBox.ok = true;
266
+ if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
267
+ this.filePickBox.customButton = true;
268
+ this.filePickBox.customLabel = ( localizeWithPath(
269
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
270
+ 'remoteFileDialog.local',
271
+ 'Show Local'
272
+ ));
273
+ let action;
274
+ if (isSave) {
275
+ action = SaveLocalFileCommand;
276
+ }
277
+ else {
278
+ action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderCommand : OpenLocalFileCommand) : OpenLocalFolderCommand;
279
+ }
280
+ const keybinding = this.keybindingService.lookupKeybinding(action.ID);
281
+ if (keybinding) {
282
+ const label = keybinding.getLabel();
283
+ if (label) {
284
+ this.filePickBox.customHover = format('{0} ({1})', action.LABEL, label);
285
+ }
286
+ }
287
+ }
288
+ let isResolving = 0;
289
+ let isAcceptHandled = false;
290
+ this.currentFolder = dirname(homedir);
291
+ this.userEnteredPathSegment = '';
292
+ this.autoCompletePathSegment = '';
293
+ this.filePickBox.title = this.options.title;
294
+ this.filePickBox.value = this.pathFromUri(this.currentFolder, true);
295
+ this.filePickBox.valueSelection = [this.filePickBox.value.length, this.filePickBox.value.length];
296
+ function doResolve(dialog, uri) {
297
+ if (uri) {
298
+ uri = addTrailingPathSeparator(uri, dialog.separator);
299
+ uri = removeTrailingPathSeparator(uri);
300
+ }
301
+ resolve(uri);
302
+ dialog.contextKey.set(false);
303
+ dialog.filePickBox.dispose();
304
+ dispose(dialog.disposables);
305
+ }
306
+ this.filePickBox.onDidCustom(() => {
307
+ if (isAcceptHandled || this.busy) {
308
+ return;
309
+ }
310
+ isAcceptHandled = true;
311
+ isResolving++;
312
+ if (this.options.availableFileSystems && (this.options.availableFileSystems.length > 1)) {
313
+ this.options.availableFileSystems = this.options.availableFileSystems.slice(1);
314
+ }
315
+ this.filePickBox.hide();
316
+ if (isSave) {
317
+ return this.fileDialogService.showSaveDialog(this.options).then(result => {
318
+ doResolve(this, result);
319
+ });
320
+ }
321
+ else {
322
+ return this.fileDialogService.showOpenDialog(this.options).then(result => {
323
+ doResolve(this, result ? result[0] : undefined);
324
+ });
325
+ }
326
+ });
327
+ function handleAccept(dialog) {
328
+ if (dialog.busy) {
329
+ dialog.onBusyChangeEmitter.event((busy) => {
330
+ if (!busy) {
331
+ handleAccept(dialog);
332
+ }
333
+ });
334
+ return;
335
+ }
336
+ else if (isAcceptHandled) {
337
+ return;
338
+ }
339
+ isAcceptHandled = true;
340
+ isResolving++;
341
+ dialog.onDidAccept().then(resolveValue => {
342
+ if (resolveValue) {
343
+ dialog.filePickBox.hide();
344
+ doResolve(dialog, resolveValue);
345
+ }
346
+ else if (dialog.hidden) {
347
+ doResolve(dialog, undefined);
348
+ }
349
+ else {
350
+ isResolving--;
351
+ isAcceptHandled = false;
352
+ }
353
+ });
354
+ }
355
+ this.filePickBox.onDidAccept(_ => {
356
+ handleAccept(this);
357
+ });
358
+ this.filePickBox.onDidChangeActive(i => {
359
+ isAcceptHandled = false;
360
+ if ((i.length === 1) && this.isSelectionChangeFromUser()) {
361
+ this.filePickBox.validationMessage = undefined;
362
+ const userPath = this.constructFullUserPath();
363
+ if (!equalsIgnoreCase(this.filePickBox.value.substring(0, userPath.length), userPath)) {
364
+ this.filePickBox.valueSelection = [0, this.filePickBox.value.length];
365
+ this.insertText(userPath, userPath);
366
+ }
367
+ this.setAutoComplete(userPath, this.userEnteredPathSegment, i[0], true);
368
+ }
369
+ });
370
+ this.filePickBox.onDidChangeValue(async (value) => {
371
+ return this.handleValueChange(value);
372
+ });
373
+ this.filePickBox.onDidHide(() => {
374
+ this.hidden = true;
375
+ if (isResolving === 0) {
376
+ doResolve(this, undefined);
377
+ }
378
+ });
379
+ this.filePickBox.show();
380
+ this.contextKey.set(true);
381
+ this.updateItems(homedir, true, this.trailing).then(() => {
382
+ if (this.trailing) {
383
+ this.filePickBox.valueSelection = [this.filePickBox.value.length - this.trailing.length, this.filePickBox.value.length - ext.length];
384
+ }
385
+ else {
386
+ this.filePickBox.valueSelection = [this.filePickBox.value.length, this.filePickBox.value.length];
387
+ }
388
+ this.busy = false;
389
+ });
390
+ }));
391
+ }
392
+ async handleValueChange(value) {
393
+ try {
394
+ if (this.isValueChangeFromUser()) {
395
+ if (!equalsIgnoreCase(value, this.constructFullUserPath()) && !this.isBadSubpath(value)) {
396
+ this.filePickBox.validationMessage = undefined;
397
+ const filePickBoxUri = this.filePickBoxValue();
398
+ let updated = UpdateResult.NotUpdated;
399
+ if (!extUriIgnorePathCase.isEqual(this.currentFolder, filePickBoxUri)) {
400
+ updated = await this.tryUpdateItems(value, filePickBoxUri);
401
+ }
402
+ if ((updated === UpdateResult.NotUpdated) || (updated === UpdateResult.UpdatedWithTrailing)) {
403
+ this.setActiveItems(value);
404
+ }
405
+ }
406
+ else {
407
+ this.filePickBox.activeItems = [];
408
+ this.userEnteredPathSegment = '';
409
+ }
410
+ }
411
+ }
412
+ catch {
413
+ }
414
+ }
415
+ isBadSubpath(value) {
416
+ return this.badPath && (value.length > this.badPath.length) && equalsIgnoreCase(value.substring(0, this.badPath.length), this.badPath);
417
+ }
418
+ isValueChangeFromUser() {
419
+ if (equalsIgnoreCase(this.filePickBox.value, this.pathAppend(this.currentFolder, this.userEnteredPathSegment + this.autoCompletePathSegment))) {
420
+ return false;
421
+ }
422
+ return true;
423
+ }
424
+ isSelectionChangeFromUser() {
425
+ if (this.activeItem === (this.filePickBox.activeItems ? this.filePickBox.activeItems[0] : undefined)) {
426
+ return false;
427
+ }
428
+ return true;
429
+ }
430
+ constructFullUserPath() {
431
+ const currentFolderPath = this.pathFromUri(this.currentFolder);
432
+ if (equalsIgnoreCase(this.filePickBox.value.substr(0, this.userEnteredPathSegment.length), this.userEnteredPathSegment)) {
433
+ if (equalsIgnoreCase(this.filePickBox.value.substr(0, currentFolderPath.length), currentFolderPath)) {
434
+ return currentFolderPath;
435
+ }
436
+ else {
437
+ return this.userEnteredPathSegment;
438
+ }
439
+ }
440
+ else {
441
+ return this.pathAppend(this.currentFolder, this.userEnteredPathSegment);
442
+ }
443
+ }
444
+ filePickBoxValue() {
445
+ const directUri = this.remoteUriFrom(this.filePickBox.value.trimRight(), this.currentFolder);
446
+ const currentPath = this.pathFromUri(this.currentFolder);
447
+ if (equalsIgnoreCase(this.filePickBox.value, currentPath)) {
448
+ return this.currentFolder;
449
+ }
450
+ const currentDisplayUri = this.remoteUriFrom(currentPath, this.currentFolder);
451
+ const relativePath$1 = relativePath(currentDisplayUri, directUri);
452
+ const isSameRoot = (this.filePickBox.value.length > 1 && currentPath.length > 1) ? equalsIgnoreCase(this.filePickBox.value.substr(0, 2), currentPath.substr(0, 2)) : false;
453
+ if (relativePath$1 && isSameRoot) {
454
+ let path = joinPath(this.currentFolder, relativePath$1);
455
+ const directBasename = basename(directUri);
456
+ if ((directBasename === '.') || (directBasename === '..')) {
457
+ path = this.remoteUriFrom(this.pathAppend(path, directBasename), this.currentFolder);
458
+ }
459
+ return hasTrailingPathSeparator(directUri) ? addTrailingPathSeparator(path) : path;
460
+ }
461
+ else {
462
+ return directUri;
463
+ }
464
+ }
465
+ async onDidAccept() {
466
+ this.busy = true;
467
+ if (this.filePickBox.activeItems.length === 1) {
468
+ const item = this.filePickBox.selectedItems[0];
469
+ if (item.isFolder) {
470
+ if (this.trailing) {
471
+ await this.updateItems(item.uri, true, this.trailing);
472
+ }
473
+ else {
474
+ const newPath = this.pathFromUri(item.uri);
475
+ if (startsWithIgnoreCase(newPath, this.filePickBox.value) && (equalsIgnoreCase(item.label, basename(item.uri)))) {
476
+ this.filePickBox.valueSelection = [this.pathFromUri(this.currentFolder).length, this.filePickBox.value.length];
477
+ this.insertText(newPath, this.basenameWithTrailingSlash(item.uri));
478
+ }
479
+ else if ((item.label === '..') && startsWithIgnoreCase(this.filePickBox.value, newPath)) {
480
+ this.filePickBox.valueSelection = [newPath.length, this.filePickBox.value.length];
481
+ this.insertText(newPath, '');
482
+ }
483
+ else {
484
+ await this.updateItems(item.uri, true);
485
+ }
486
+ }
487
+ this.filePickBox.busy = false;
488
+ return;
489
+ }
490
+ }
491
+ else {
492
+ if ((await this.tryUpdateItems(this.filePickBox.value, this.filePickBoxValue())) !== UpdateResult.NotUpdated) {
493
+ this.filePickBox.busy = false;
494
+ return;
495
+ }
496
+ }
497
+ let resolveValue;
498
+ if (this.filePickBox.activeItems.length === 0) {
499
+ resolveValue = this.filePickBoxValue();
500
+ }
501
+ else if (this.filePickBox.activeItems.length === 1) {
502
+ resolveValue = this.filePickBox.selectedItems[0].uri;
503
+ }
504
+ if (resolveValue) {
505
+ resolveValue = this.addPostfix(resolveValue);
506
+ }
507
+ if (await this.validate(resolveValue)) {
508
+ this.busy = false;
509
+ return resolveValue;
510
+ }
511
+ this.busy = false;
512
+ return undefined;
513
+ }
514
+ root(value) {
515
+ let lastDir = value;
516
+ let dir = dirname(value);
517
+ while (!isEqual(lastDir, dir)) {
518
+ lastDir = dir;
519
+ dir = dirname(dir);
520
+ }
521
+ return dir;
522
+ }
523
+ tildaReplace(value) {
524
+ const home = this.trueHome;
525
+ if ((value.length > 0) && (value[0] === '~')) {
526
+ return joinPath(home, value.substring(1));
527
+ }
528
+ return this.remoteUriFrom(value);
529
+ }
530
+ tryAddTrailingSeparatorToDirectory(uri, stat) {
531
+ if (stat.isDirectory) {
532
+ if (!this.endsWithSlash(uri.path)) {
533
+ return addTrailingPathSeparator(uri);
534
+ }
535
+ }
536
+ return uri;
537
+ }
538
+ async tryUpdateItems(value, valueUri) {
539
+ if ((value.length > 0) && (value[0] === '~')) {
540
+ const newDir = this.tildaReplace(value);
541
+ return (await this.updateItems(newDir, true)) ? UpdateResult.UpdatedWithTrailing : UpdateResult.Updated;
542
+ }
543
+ else if (value === '\\') {
544
+ valueUri = this.root(this.currentFolder);
545
+ value = this.pathFromUri(valueUri);
546
+ return (await this.updateItems(valueUri, true)) ? UpdateResult.UpdatedWithTrailing : UpdateResult.Updated;
547
+ }
548
+ else {
549
+ const newFolderIsOldFolder = extUriIgnorePathCase.isEqual(this.currentFolder, valueUri);
550
+ const newFolderIsSubFolder = extUriIgnorePathCase.isEqual(this.currentFolder, dirname(valueUri));
551
+ const newFolderIsParent = extUriIgnorePathCase.isEqualOrParent(this.currentFolder, dirname(valueUri));
552
+ const newFolderIsUnrelated = !newFolderIsParent && !newFolderIsSubFolder;
553
+ if (!newFolderIsOldFolder && (this.endsWithSlash(value) || newFolderIsParent || newFolderIsUnrelated)) {
554
+ let stat;
555
+ try {
556
+ stat = await this.fileService.stat(valueUri);
557
+ }
558
+ catch (e) {
559
+ }
560
+ if (stat && stat.isDirectory && (basename(valueUri) !== '.') && this.endsWithSlash(value)) {
561
+ valueUri = this.tryAddTrailingSeparatorToDirectory(valueUri, stat);
562
+ return (await this.updateItems(valueUri)) ? UpdateResult.UpdatedWithTrailing : UpdateResult.Updated;
563
+ }
564
+ else if (this.endsWithSlash(value)) {
565
+ this.filePickBox.validationMessage = ( localizeWithPath(
566
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
567
+ 'remoteFileDialog.badPath',
568
+ 'The path does not exist.'
569
+ ));
570
+ this.badPath = value;
571
+ return UpdateResult.InvalidPath;
572
+ }
573
+ else {
574
+ let inputUriDirname = dirname(valueUri);
575
+ const currentFolderWithoutSep = removeTrailingPathSeparator(addTrailingPathSeparator(this.currentFolder));
576
+ const inputUriDirnameWithoutSep = removeTrailingPathSeparator(addTrailingPathSeparator(inputUriDirname));
577
+ if (!extUriIgnorePathCase.isEqual(currentFolderWithoutSep, inputUriDirnameWithoutSep)
578
+ && (!/^[a-zA-Z]:$/.test(this.filePickBox.value)
579
+ || !equalsIgnoreCase(this.pathFromUri(this.currentFolder).substring(0, this.filePickBox.value.length), this.filePickBox.value))) {
580
+ let statWithoutTrailing;
581
+ try {
582
+ statWithoutTrailing = await this.fileService.stat(inputUriDirname);
583
+ }
584
+ catch (e) {
585
+ }
586
+ if (statWithoutTrailing && statWithoutTrailing.isDirectory) {
587
+ this.badPath = undefined;
588
+ inputUriDirname = this.tryAddTrailingSeparatorToDirectory(inputUriDirname, statWithoutTrailing);
589
+ return (await this.updateItems(inputUriDirname, false, basename(valueUri))) ? UpdateResult.UpdatedWithTrailing : UpdateResult.Updated;
590
+ }
591
+ }
592
+ }
593
+ }
594
+ }
595
+ this.badPath = undefined;
596
+ return UpdateResult.NotUpdated;
597
+ }
598
+ tryUpdateTrailing(value) {
599
+ const ext = extname(value);
600
+ if (this.trailing && ext) {
601
+ this.trailing = basename(value);
602
+ }
603
+ }
604
+ setActiveItems(value) {
605
+ value = this.pathFromUri(this.tildaReplace(value));
606
+ const asUri = this.remoteUriFrom(value);
607
+ const inputBasename = basename(asUri);
608
+ const userPath = this.constructFullUserPath();
609
+ const pathsEqual = equalsIgnoreCase(userPath, value.substring(0, userPath.length)) ||
610
+ equalsIgnoreCase(value, userPath.substring(0, value.length));
611
+ if (pathsEqual) {
612
+ let hasMatch = false;
613
+ for (let i = 0; i < this.filePickBox.items.length; i++) {
614
+ const item = this.filePickBox.items[i];
615
+ if (this.setAutoComplete(value, inputBasename, item)) {
616
+ hasMatch = true;
617
+ break;
618
+ }
619
+ }
620
+ if (!hasMatch) {
621
+ const userBasename = inputBasename.length >= 2 ? userPath.substring(userPath.length - inputBasename.length + 2) : '';
622
+ this.userEnteredPathSegment = (userBasename === inputBasename) ? inputBasename : '';
623
+ this.autoCompletePathSegment = '';
624
+ this.filePickBox.activeItems = [];
625
+ this.tryUpdateTrailing(asUri);
626
+ }
627
+ }
628
+ else {
629
+ this.userEnteredPathSegment = inputBasename;
630
+ this.autoCompletePathSegment = '';
631
+ this.filePickBox.activeItems = [];
632
+ this.tryUpdateTrailing(asUri);
633
+ }
634
+ }
635
+ setAutoComplete(startingValue, startingBasename, quickPickItem, force = false) {
636
+ if (this.busy) {
637
+ this.userEnteredPathSegment = startingBasename;
638
+ this.autoCompletePathSegment = '';
639
+ return false;
640
+ }
641
+ const itemBasename = quickPickItem.label;
642
+ if (itemBasename === '..') {
643
+ this.userEnteredPathSegment = '';
644
+ this.autoCompletePathSegment = '';
645
+ this.activeItem = quickPickItem;
646
+ if (force) {
647
+ getActiveDocument().execCommand('insertText', false, '');
648
+ }
649
+ return false;
650
+ }
651
+ else if (!force && (itemBasename.length >= startingBasename.length) && equalsIgnoreCase(itemBasename.substr(0, startingBasename.length), startingBasename)) {
652
+ this.userEnteredPathSegment = startingBasename;
653
+ this.activeItem = quickPickItem;
654
+ this.autoCompletePathSegment = '';
655
+ if (quickPickItem.isFolder || !this.trailing) {
656
+ this.filePickBox.activeItems = [quickPickItem];
657
+ }
658
+ else {
659
+ this.filePickBox.activeItems = [];
660
+ }
661
+ return true;
662
+ }
663
+ else if (force && (!equalsIgnoreCase(this.basenameWithTrailingSlash(quickPickItem.uri), (this.userEnteredPathSegment + this.autoCompletePathSegment)))) {
664
+ this.userEnteredPathSegment = '';
665
+ if (!this.accessibilityService.isScreenReaderOptimized()) {
666
+ this.autoCompletePathSegment = this.trimTrailingSlash(itemBasename);
667
+ }
668
+ this.activeItem = quickPickItem;
669
+ if (!this.accessibilityService.isScreenReaderOptimized()) {
670
+ this.filePickBox.valueSelection = [this.pathFromUri(this.currentFolder, true).length, this.filePickBox.value.length];
671
+ this.insertText(this.pathAppend(this.currentFolder, this.autoCompletePathSegment), this.autoCompletePathSegment);
672
+ this.filePickBox.valueSelection = [this.filePickBox.value.length - this.autoCompletePathSegment.length, this.filePickBox.value.length];
673
+ }
674
+ return true;
675
+ }
676
+ else {
677
+ this.userEnteredPathSegment = startingBasename;
678
+ this.autoCompletePathSegment = '';
679
+ return false;
680
+ }
681
+ }
682
+ insertText(wholeValue, insertText) {
683
+ if (this.filePickBox.inputHasFocus()) {
684
+ getActiveDocument().execCommand('insertText', false, insertText);
685
+ if (this.filePickBox.value !== wholeValue) {
686
+ this.filePickBox.value = wholeValue;
687
+ this.handleValueChange(wholeValue);
688
+ }
689
+ }
690
+ else {
691
+ this.filePickBox.value = wholeValue;
692
+ this.handleValueChange(wholeValue);
693
+ }
694
+ }
695
+ addPostfix(uri) {
696
+ let result = uri;
697
+ if (this.requiresTrailing && this.options.filters && this.options.filters.length > 0 && !hasTrailingPathSeparator(uri)) {
698
+ let hasExt = false;
699
+ const currentExt = extname(uri).substr(1);
700
+ for (let i = 0; i < this.options.filters.length; i++) {
701
+ for (let j = 0; j < this.options.filters[i].extensions.length; j++) {
702
+ if ((this.options.filters[i].extensions[j] === '*') || (this.options.filters[i].extensions[j] === currentExt)) {
703
+ hasExt = true;
704
+ break;
705
+ }
706
+ }
707
+ if (hasExt) {
708
+ break;
709
+ }
710
+ }
711
+ if (!hasExt) {
712
+ result = joinPath(dirname(uri), basename(uri) + '.' + this.options.filters[0].extensions[0]);
713
+ }
714
+ }
715
+ return result;
716
+ }
717
+ trimTrailingSlash(path) {
718
+ return ((path.length > 1) && this.endsWithSlash(path)) ? path.substr(0, path.length - 1) : path;
719
+ }
720
+ yesNoPrompt(uri, message) {
721
+ const prompt = this.quickInputService.createQuickPick();
722
+ prompt.title = message;
723
+ prompt.ignoreFocusOut = true;
724
+ prompt.ok = true;
725
+ prompt.customButton = true;
726
+ prompt.customLabel = ( localizeWithPath(
727
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
728
+ 'remoteFileDialog.cancel',
729
+ 'Cancel'
730
+ ));
731
+ prompt.value = this.pathFromUri(uri);
732
+ let isResolving = false;
733
+ return ( new Promise(resolve => {
734
+ prompt.onDidAccept(() => {
735
+ isResolving = true;
736
+ prompt.hide();
737
+ resolve(true);
738
+ });
739
+ prompt.onDidHide(() => {
740
+ if (!isResolving) {
741
+ resolve(false);
742
+ }
743
+ this.filePickBox.show();
744
+ this.hidden = false;
745
+ prompt.dispose();
746
+ });
747
+ prompt.onDidChangeValue(() => {
748
+ prompt.hide();
749
+ });
750
+ prompt.onDidCustom(() => {
751
+ prompt.hide();
752
+ });
753
+ prompt.show();
754
+ }));
755
+ }
756
+ async validate(uri) {
757
+ if (uri === undefined) {
758
+ this.filePickBox.validationMessage = ( localizeWithPath(
759
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
760
+ 'remoteFileDialog.invalidPath',
761
+ 'Please enter a valid path.'
762
+ ));
763
+ return Promise.resolve(false);
764
+ }
765
+ let stat;
766
+ let statDirname;
767
+ try {
768
+ statDirname = await this.fileService.stat(dirname(uri));
769
+ stat = await this.fileService.stat(uri);
770
+ }
771
+ catch (e) {
772
+ }
773
+ if (this.requiresTrailing) {
774
+ if (stat && stat.isDirectory) {
775
+ this.filePickBox.validationMessage = ( localizeWithPath(
776
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
777
+ 'remoteFileDialog.validateFolder',
778
+ 'The folder already exists. Please use a new file name.'
779
+ ));
780
+ return Promise.resolve(false);
781
+ }
782
+ else if (stat) {
783
+ const message = ( localizeWithPath(
784
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
785
+ 'remoteFileDialog.validateExisting',
786
+ '{0} already exists. Are you sure you want to overwrite it?',
787
+ basename(uri)
788
+ ));
789
+ return this.yesNoPrompt(uri, message);
790
+ }
791
+ else if (!(isValidBasename(basename(uri), this.isWindows))) {
792
+ this.filePickBox.validationMessage = ( localizeWithPath(
793
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
794
+ 'remoteFileDialog.validateBadFilename',
795
+ 'Please enter a valid file name.'
796
+ ));
797
+ return Promise.resolve(false);
798
+ }
799
+ else if (!statDirname) {
800
+ const message = ( localizeWithPath(
801
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
802
+ 'remoteFileDialog.validateCreateDirectory',
803
+ 'The folder {0} does not exist. Would you like to create it?',
804
+ basename(dirname(uri))
805
+ ));
806
+ return this.yesNoPrompt(uri, message);
807
+ }
808
+ else if (!statDirname.isDirectory) {
809
+ this.filePickBox.validationMessage = ( localizeWithPath(
810
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
811
+ 'remoteFileDialog.validateNonexistentDir',
812
+ 'Please enter a path that exists.'
813
+ ));
814
+ return Promise.resolve(false);
815
+ }
816
+ else if (statDirname.readonly || statDirname.locked) {
817
+ this.filePickBox.validationMessage = ( localizeWithPath(
818
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
819
+ 'remoteFileDialog.validateReadonlyFolder',
820
+ 'This folder cannot be used as a save destination. Please choose another folder'
821
+ ));
822
+ return Promise.resolve(false);
823
+ }
824
+ }
825
+ else {
826
+ if (!stat) {
827
+ this.filePickBox.validationMessage = ( localizeWithPath(
828
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
829
+ 'remoteFileDialog.validateNonexistentDir',
830
+ 'Please enter a path that exists.'
831
+ ));
832
+ return Promise.resolve(false);
833
+ }
834
+ else if (uri.path === '/' && this.isWindows) {
835
+ this.filePickBox.validationMessage = ( localizeWithPath(
836
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
837
+ 'remoteFileDialog.windowsDriveLetter',
838
+ 'Please start the path with a drive letter.'
839
+ ));
840
+ return Promise.resolve(false);
841
+ }
842
+ else if (stat.isDirectory && !this.allowFolderSelection) {
843
+ this.filePickBox.validationMessage = ( localizeWithPath(
844
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
845
+ 'remoteFileDialog.validateFileOnly',
846
+ 'Please select a file.'
847
+ ));
848
+ return Promise.resolve(false);
849
+ }
850
+ else if (!stat.isDirectory && !this.allowFileSelection) {
851
+ this.filePickBox.validationMessage = ( localizeWithPath(
852
+ 'vs/workbench/services/dialogs/browser/simpleFileDialog',
853
+ 'remoteFileDialog.validateFolderOnly',
854
+ 'Please select a folder.'
855
+ ));
856
+ return Promise.resolve(false);
857
+ }
858
+ }
859
+ return Promise.resolve(true);
860
+ }
861
+ async updateItems(newFolder, force = false, trailing) {
862
+ this.busy = true;
863
+ this.autoCompletePathSegment = '';
864
+ const isSave = !!trailing;
865
+ let result = false;
866
+ const updatingPromise = createCancelablePromise(async (token) => {
867
+ let folderStat;
868
+ try {
869
+ folderStat = await this.fileService.resolve(newFolder);
870
+ if (!folderStat.isDirectory) {
871
+ trailing = basename(newFolder);
872
+ newFolder = dirname(newFolder);
873
+ folderStat = undefined;
874
+ result = true;
875
+ }
876
+ }
877
+ catch (e) {
878
+ }
879
+ const newValue = trailing ? this.pathAppend(newFolder, trailing) : this.pathFromUri(newFolder, true);
880
+ this.currentFolder = this.endsWithSlash(newFolder.path) ? newFolder : addTrailingPathSeparator(newFolder, this.separator);
881
+ this.userEnteredPathSegment = trailing ? trailing : '';
882
+ return this.createItems(folderStat, this.currentFolder, token).then(items => {
883
+ if (token.isCancellationRequested) {
884
+ this.busy = false;
885
+ return false;
886
+ }
887
+ this.filePickBox.itemActivation = ItemActivation.NONE;
888
+ this.filePickBox.items = items;
889
+ if (!equalsIgnoreCase(this.filePickBox.value, newValue) && force) {
890
+ this.filePickBox.valueSelection = [0, this.filePickBox.value.length];
891
+ this.insertText(newValue, newValue);
892
+ }
893
+ if (force && trailing && isSave) {
894
+ this.filePickBox.valueSelection = [this.filePickBox.value.length - trailing.length, this.filePickBox.value.length - trailing.length];
895
+ }
896
+ else if (!trailing) {
897
+ this.filePickBox.valueSelection = [this.filePickBox.value.length, this.filePickBox.value.length];
898
+ }
899
+ this.busy = false;
900
+ this.updatingPromise = undefined;
901
+ return result;
902
+ });
903
+ });
904
+ if (this.updatingPromise !== undefined) {
905
+ this.updatingPromise.cancel();
906
+ }
907
+ this.updatingPromise = updatingPromise;
908
+ return updatingPromise;
909
+ }
910
+ pathFromUri(uri, endWithSeparator = false) {
911
+ let result = normalizeDriveLetter(uri.fsPath, this.isWindows).replace(/\n/g, '');
912
+ if (this.separator === '/') {
913
+ result = result.replace(/\\/g, this.separator);
914
+ }
915
+ else {
916
+ result = result.replace(/\//g, this.separator);
917
+ }
918
+ if (endWithSeparator && !this.endsWithSlash(result)) {
919
+ result = result + this.separator;
920
+ }
921
+ return result;
922
+ }
923
+ pathAppend(uri, additional) {
924
+ if ((additional === '..') || (additional === '.')) {
925
+ const basePath = this.pathFromUri(uri, true);
926
+ return basePath + additional;
927
+ }
928
+ else {
929
+ return this.pathFromUri(joinPath(uri, additional));
930
+ }
931
+ }
932
+ async checkIsWindowsOS() {
933
+ let isWindowsOS = isWindows;
934
+ const env = await this.getRemoteAgentEnvironment();
935
+ if (env) {
936
+ isWindowsOS = env.os === 1 ;
937
+ }
938
+ return isWindowsOS;
939
+ }
940
+ endsWithSlash(s) {
941
+ return /[\/\\]$/.test(s);
942
+ }
943
+ basenameWithTrailingSlash(fullPath) {
944
+ const child = this.pathFromUri(fullPath, true);
945
+ const parent = this.pathFromUri(dirname(fullPath), true);
946
+ return child.substring(parent.length);
947
+ }
948
+ async createBackItem(currFolder) {
949
+ const fileRepresentationCurr = this.currentFolder.with({ scheme: Schemas.file, authority: '' });
950
+ const fileRepresentationParent = dirname(fileRepresentationCurr);
951
+ if (!isEqual(fileRepresentationCurr, fileRepresentationParent)) {
952
+ const parentFolder = dirname(currFolder);
953
+ if (await this.fileService.exists(parentFolder)) {
954
+ return { label: '..', uri: addTrailingPathSeparator(parentFolder, this.separator), isFolder: true };
955
+ }
956
+ }
957
+ return undefined;
958
+ }
959
+ async createItems(folder, currentFolder, token) {
960
+ const result = [];
961
+ const backDir = await this.createBackItem(currentFolder);
962
+ try {
963
+ if (!folder) {
964
+ folder = await this.fileService.resolve(currentFolder);
965
+ }
966
+ const items = folder.children ? await Promise.all(( folder.children.map(child => this.createItem(child, currentFolder, token)))) : [];
967
+ for (const item of items) {
968
+ if (item) {
969
+ result.push(item);
970
+ }
971
+ }
972
+ }
973
+ catch (e) {
974
+ console.log(e);
975
+ }
976
+ if (token.isCancellationRequested) {
977
+ return [];
978
+ }
979
+ const sorted = result.sort((i1, i2) => {
980
+ if (i1.isFolder !== i2.isFolder) {
981
+ return i1.isFolder ? -1 : 1;
982
+ }
983
+ const trimmed1 = this.endsWithSlash(i1.label) ? i1.label.substr(0, i1.label.length - 1) : i1.label;
984
+ const trimmed2 = this.endsWithSlash(i2.label) ? i2.label.substr(0, i2.label.length - 1) : i2.label;
985
+ return trimmed1.localeCompare(trimmed2);
986
+ });
987
+ if (backDir) {
988
+ sorted.unshift(backDir);
989
+ }
990
+ return sorted;
991
+ }
992
+ filterFile(file) {
993
+ if (this.options.filters) {
994
+ for (let i = 0; i < this.options.filters.length; i++) {
995
+ for (let j = 0; j < this.options.filters[i].extensions.length; j++) {
996
+ const testExt = this.options.filters[i].extensions[j];
997
+ if ((testExt === '*') || (file.path.endsWith('.' + testExt))) {
998
+ return true;
999
+ }
1000
+ }
1001
+ }
1002
+ return false;
1003
+ }
1004
+ return true;
1005
+ }
1006
+ async createItem(stat, parent, token) {
1007
+ if (token.isCancellationRequested) {
1008
+ return undefined;
1009
+ }
1010
+ let fullPath = joinPath(parent, stat.name);
1011
+ if (stat.isDirectory) {
1012
+ const filename = basename(fullPath);
1013
+ fullPath = addTrailingPathSeparator(fullPath, this.separator);
1014
+ return { label: filename, uri: fullPath, isFolder: true, iconClasses: getIconClasses(this.modelService, this.languageService, fullPath || undefined, FileKind.FOLDER) };
1015
+ }
1016
+ else if (!stat.isDirectory && this.allowFileSelection && this.filterFile(fullPath)) {
1017
+ return { label: stat.name, uri: fullPath, isFolder: false, iconClasses: getIconClasses(this.modelService, this.languageService, fullPath || undefined) };
1018
+ }
1019
+ return undefined;
1020
+ }
1021
+ };
1022
+ SimpleFileDialog = ( __decorate([
1023
+ ( __param(0, IFileService)),
1024
+ ( __param(1, IQuickInputService)),
1025
+ ( __param(2, ILabelService)),
1026
+ ( __param(3, IWorkspaceContextService)),
1027
+ ( __param(4, INotificationService)),
1028
+ ( __param(5, IFileDialogService)),
1029
+ ( __param(6, IModelService)),
1030
+ ( __param(7, ILanguageService)),
1031
+ ( __param(8, IWorkbenchEnvironmentService)),
1032
+ ( __param(9, IRemoteAgentService)),
1033
+ ( __param(10, IPathService)),
1034
+ ( __param(11, IKeybindingService)),
1035
+ ( __param(12, IContextKeyService)),
1036
+ ( __param(13, IAccessibilityService))
1037
+ ], SimpleFileDialog));
1038
+
1039
+ export { OpenLocalFileCommand, OpenLocalFileFolderCommand, OpenLocalFolderCommand, RemoteFileDialogContext, SaveLocalFileCommand, SimpleFileDialog };