mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 01:25:38 -05:00
Merge from vscode 2b0b9136329c181a9e381463a1f7dc3a2d105a34 (#4880)
This commit is contained in:
@@ -7,33 +7,33 @@ import * as fs from 'fs';
|
||||
import { basename, normalize, join, dirname } from 'vs/base/common/path';
|
||||
import { localize } from 'vs/nls';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { assign, mixin, equals } from 'vs/base/common/objects';
|
||||
import { assign, mixin } from 'vs/base/common/objects';
|
||||
import { IBackupMainService, IEmptyWindowBackupInfo } from 'vs/platform/backup/common/backup';
|
||||
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
import { IStateService } from 'vs/platform/state/common/state';
|
||||
import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window';
|
||||
import { hasArgs, asArray } from 'vs/platform/environment/node/argv';
|
||||
import { ipcMain as ipc, screen, BrowserWindow, dialog, systemPreferences } from 'electron';
|
||||
import { ipcMain as ipc, screen, BrowserWindow, dialog, systemPreferences, FileFilter } from 'electron';
|
||||
import { parseLineAndColumnAware } from 'vs/code/node/paths';
|
||||
import { ILifecycleService, UnloadReason, LifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, INativeOpenDialogOptions, IPathsToWaitFor, IEnterWorkspaceResult, IMessageBoxResult, INewWindowOptions, IURIToOpen, URIType, OpenDialogOptions } from 'vs/platform/windows/common/windows';
|
||||
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, INativeOpenDialogOptions, IPathsToWaitFor, IEnterWorkspaceResult, IMessageBoxResult, INewWindowOptions, IURIToOpen, isFileToOpen, isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/windows/common/windows';
|
||||
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri } from 'vs/code/node/windowsFinder';
|
||||
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
|
||||
import { IHistoryMainService, IRecent } from 'vs/platform/history/common/history';
|
||||
import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { IWorkspacesMainService, IWorkspaceIdentifier, WORKSPACE_FILTER, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspacesMainService, IWorkspaceIdentifier, WORKSPACE_FILTER, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { mnemonicButtonLabel } from 'vs/base/common/labels';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { normalizeNFC } from 'vs/base/common/normalization';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Queue } from 'vs/base/common/async';
|
||||
import { exists } from 'vs/base/node/pfs';
|
||||
import { exists, dirExists } from 'vs/base/node/pfs';
|
||||
import { getComparisonKey, isEqual, normalizePath, basename as resourcesBasename, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources';
|
||||
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage';
|
||||
@@ -87,7 +87,6 @@ interface IOpenBrowserWindowOptions {
|
||||
interface IPathParseOptions {
|
||||
ignoreFileNotFound?: boolean;
|
||||
gotoLineMode?: boolean;
|
||||
forceOpenWorkspaceAsFile?: boolean;
|
||||
remoteAuthority?: string;
|
||||
}
|
||||
|
||||
@@ -206,7 +205,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
this.windowsState.openedWindows = [];
|
||||
}
|
||||
|
||||
this.dialogs = new Dialogs(environmentService, telemetryService, stateService, this);
|
||||
this.dialogs = new Dialogs(stateService, this);
|
||||
this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, this);
|
||||
}
|
||||
|
||||
@@ -219,7 +218,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
private registerListeners(): void {
|
||||
|
||||
// React to workbench ready events from windows
|
||||
ipc.on('vscode:workbenchReady', (event: any, windowId: number) => {
|
||||
ipc.on('vscode:workbenchReady', (event: Electron.Event, windowId: number) => {
|
||||
this.logService.trace('IPC#vscode-workbenchReady');
|
||||
|
||||
const win = this.getWindowById(windowId);
|
||||
@@ -843,26 +842,26 @@ export class WindowsManager implements IWindowsMainService {
|
||||
private doExtractPathsFromAPI(openConfig: IOpenConfiguration): IPathToOpen[] {
|
||||
const pathsToOpen: IPathToOpen[] = [];
|
||||
const cli = openConfig.cli;
|
||||
const parseOptions: IPathParseOptions = { gotoLineMode: cli && cli.goto, forceOpenWorkspaceAsFile: openConfig.forceOpenWorkspaceAsFile };
|
||||
const parseOptions: IPathParseOptions = { gotoLineMode: cli && cli.goto };
|
||||
for (const pathToOpen of openConfig.urisToOpen || []) {
|
||||
if (!pathToOpen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const path = this.parseUri(pathToOpen.uri, pathToOpen.typeHint, parseOptions);
|
||||
const path = this.parseUri(pathToOpen, parseOptions);
|
||||
if (path) {
|
||||
path.label = pathToOpen.label;
|
||||
pathsToOpen.push(path);
|
||||
} else {
|
||||
|
||||
const uri = resourceFromURIToOpen(pathToOpen);
|
||||
// Warn about the invalid URI or path
|
||||
let message, detail;
|
||||
if (pathToOpen.uri.scheme === Schemas.file) {
|
||||
if (uri.scheme === Schemas.file) {
|
||||
message = localize('pathNotExistTitle', "Path does not exist");
|
||||
detail = localize('pathNotExistDetail', "The path '{0}' does not seem to exist anymore on disk.", pathToOpen.uri.fsPath);
|
||||
detail = localize('pathNotExistDetail', "The path '{0}' does not seem to exist anymore on disk.", uri.fsPath);
|
||||
} else {
|
||||
message = localize('uriInvalidTitle', "URI can not be opened");
|
||||
detail = localize('uriInvalidDetail', "The URI '{0}' is not valid and can not be opened.", pathToOpen.uri.toString());
|
||||
detail = localize('uriInvalidDetail', "The URI '{0}' is not valid and can not be opened.", uri.toString());
|
||||
}
|
||||
const options: Electron.MessageBoxOptions = {
|
||||
title: product.nameLong,
|
||||
@@ -885,19 +884,25 @@ export class WindowsManager implements IWindowsMainService {
|
||||
|
||||
// folder uris
|
||||
const folderUris = asArray(cli['folder-uri']);
|
||||
for (let folderUri of folderUris) {
|
||||
const path = this.parseUri(this.argToUri(folderUri), 'folder', parseOptions);
|
||||
if (path) {
|
||||
pathsToOpen.push(path);
|
||||
for (let f of folderUris) {
|
||||
const folderUri = this.argToUri(f);
|
||||
if (folderUri) {
|
||||
const path = this.parseUri({ folderUri }, parseOptions);
|
||||
if (path) {
|
||||
pathsToOpen.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// file uris
|
||||
const fileUris = asArray(cli['file-uri']);
|
||||
for (let fileUri of fileUris) {
|
||||
const path = this.parseUri(this.argToUri(fileUri), 'file');
|
||||
if (path) {
|
||||
pathsToOpen.push(path);
|
||||
for (let f of fileUris) {
|
||||
const fileUri = this.argToUri(f);
|
||||
if (fileUri) {
|
||||
const path = this.parseUri({ fileUri }, parseOptions);
|
||||
if (path) {
|
||||
pathsToOpen.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -944,12 +949,12 @@ export class WindowsManager implements IWindowsMainService {
|
||||
const windowsToOpen: IPathToOpen[] = [];
|
||||
for (const openedWindow of openedWindows) {
|
||||
if (openedWindow.workspace) { // Workspaces
|
||||
const pathToOpen = this.parseUri(openedWindow.workspace.configPath, 'file', { remoteAuthority: openedWindow.remoteAuthority });
|
||||
const pathToOpen = this.parseUri({ workspaceUri: openedWindow.workspace.configPath }, { remoteAuthority: openedWindow.remoteAuthority });
|
||||
if (pathToOpen && pathToOpen.workspace) {
|
||||
windowsToOpen.push(pathToOpen);
|
||||
}
|
||||
} else if (openedWindow.folderUri) { // Folders
|
||||
const pathToOpen = this.parseUri(openedWindow.folderUri, 'folder', { remoteAuthority: openedWindow.remoteAuthority });
|
||||
const pathToOpen = this.parseUri({ folderUri: openedWindow.folderUri }, { remoteAuthority: openedWindow.remoteAuthority });
|
||||
if (pathToOpen && pathToOpen.folderUri) {
|
||||
windowsToOpen.push(pathToOpen);
|
||||
}
|
||||
@@ -975,7 +980,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
restoreWindows = 'all'; // always reopen all windows when an update was applied
|
||||
} else {
|
||||
const windowConfig = this.configurationService.getValue<IWindowSettings>('window');
|
||||
restoreWindows = ((windowConfig && windowConfig.restoreWindows) || 'one') as RestoreWindowsSetting;
|
||||
restoreWindows = ((windowConfig && windowConfig.restoreWindows) || 'one');
|
||||
|
||||
if (['all', 'folders', 'one', 'none'].indexOf(restoreWindows) === -1) {
|
||||
restoreWindows = 'one';
|
||||
@@ -999,12 +1004,13 @@ export class WindowsManager implements IWindowsMainService {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private parseUri(uri: URI | undefined, typeHint?: URIType, options: IPathParseOptions = {}): IPathToOpen | undefined {
|
||||
if (!uri || !uri.scheme) {
|
||||
private parseUri(uriToOpen: IURIToOpen, options: IPathParseOptions = {}): IPathToOpen | undefined {
|
||||
if (!uriToOpen) {
|
||||
return undefined;
|
||||
}
|
||||
let uri = resourceFromURIToOpen(uriToOpen);
|
||||
if (uri.scheme === Schemas.file) {
|
||||
return this.parsePath(uri.fsPath, options);
|
||||
return this.parsePath(uri.fsPath, options, isFileToOpen(uriToOpen));
|
||||
}
|
||||
|
||||
// open remote if either specified in the cli or if it's a remotehost URI
|
||||
@@ -1013,21 +1019,12 @@ export class WindowsManager implements IWindowsMainService {
|
||||
// normalize URI
|
||||
uri = normalizePath(uri);
|
||||
|
||||
|
||||
// remove trailing slash
|
||||
if (hasTrailingPathSeparator(uri)) {
|
||||
uri = removeTrailingPathSeparator(uri);
|
||||
if (!typeHint) {
|
||||
typeHint = 'folder';
|
||||
}
|
||||
}
|
||||
|
||||
// if there's no type hint
|
||||
if (!typeHint && (hasWorkspaceFileExtension(uri.path) || options.gotoLineMode)) {
|
||||
typeHint = 'file';
|
||||
}
|
||||
|
||||
if (typeHint === 'file') {
|
||||
if (isFileToOpen(uriToOpen)) {
|
||||
if (options.gotoLineMode) {
|
||||
const parsedPath = parseLineAndColumnAware(uri.path);
|
||||
return {
|
||||
@@ -1037,16 +1034,15 @@ export class WindowsManager implements IWindowsMainService {
|
||||
remoteAuthority
|
||||
};
|
||||
}
|
||||
if (hasWorkspaceFileExtension(uri.path) && !options.forceOpenWorkspaceAsFile) {
|
||||
return {
|
||||
workspace: getWorkspaceIdentifier(uri),
|
||||
remoteAuthority
|
||||
};
|
||||
}
|
||||
return {
|
||||
fileUri: uri,
|
||||
remoteAuthority
|
||||
};
|
||||
} else if (isWorkspaceToOpen(uriToOpen)) {
|
||||
return {
|
||||
workspace: getWorkspaceIdentifier(uri),
|
||||
remoteAuthority
|
||||
};
|
||||
}
|
||||
return {
|
||||
folderUri: uri,
|
||||
@@ -1054,7 +1050,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
};
|
||||
}
|
||||
|
||||
private parsePath(anyPath: string, options: IPathParseOptions): IPathToOpen | undefined {
|
||||
private parsePath(anyPath: string, options: IPathParseOptions, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined {
|
||||
if (!anyPath) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1079,7 +1075,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
if (candidateStat.isFile()) {
|
||||
|
||||
// Workspace (unless disabled via flag)
|
||||
if (!options.forceOpenWorkspaceAsFile) {
|
||||
if (!forceOpenWorkspaceAsFile) {
|
||||
const workspace = this.workspacesMainService.resolveLocalWorkspaceSync(URI.file(candidate));
|
||||
if (workspace) {
|
||||
return { workspace: { id: workspace.id, configPath: workspace.configPath }, remoteAuthority: workspace.remoteAuthority };
|
||||
@@ -1452,7 +1448,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
// Compute x/y based on display bounds
|
||||
// Note: important to use Math.round() because Electron does not seem to be too happy about
|
||||
// display coordinates that are not absolute numbers.
|
||||
let state = defaultWindowState() as INewWindowState;
|
||||
let state = defaultWindowState();
|
||||
state.x = Math.round(displayToUse.bounds.x + (displayToUse.bounds.width / 2) - (state.width! / 2));
|
||||
state.y = Math.round(displayToUse.bounds.y + (displayToUse.bounds.height / 2) - (state.height! / 2));
|
||||
|
||||
@@ -1482,7 +1478,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
state = this.ensureNoOverlap(state);
|
||||
}
|
||||
|
||||
state.hasDefaultState = true; // flag as default state
|
||||
(state as INewWindowState).hasDefaultState = true; // flag as default state
|
||||
|
||||
return state;
|
||||
}
|
||||
@@ -1537,10 +1533,6 @@ export class WindowsManager implements IWindowsMainService {
|
||||
return result;
|
||||
}
|
||||
|
||||
pickWorkspaceAndOpen(options: INativeOpenDialogOptions): void {
|
||||
this.workspacesManager.pickWorkspaceAndOpen(options);
|
||||
}
|
||||
|
||||
focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow {
|
||||
const lastActive = this.getLastActiveWindow();
|
||||
if (lastActive) {
|
||||
@@ -1717,49 +1709,83 @@ export class WindowsManager implements IWindowsMainService {
|
||||
this._onWindowClose.fire(win.id);
|
||||
}
|
||||
|
||||
pickFileFolderAndOpen(options: INativeOpenDialogOptions): void {
|
||||
this.doPickAndOpen(options, true /* pick folders */, true /* pick files */);
|
||||
async pickFileFolderAndOpen(options: INativeOpenDialogOptions): Promise<void> {
|
||||
const title = localize('open', "Open");
|
||||
const paths = await this.dialogs.pick({ ...options, pickFolders: true, pickFiles: true, title });
|
||||
if (paths) {
|
||||
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData);
|
||||
const urisToOpen = await Promise.all(paths.map(path => {
|
||||
return dirExists(path).then(isDir => isDir ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) });
|
||||
}));
|
||||
this.open({
|
||||
context: OpenContext.DIALOG,
|
||||
contextWindowId: options.windowId,
|
||||
cli: this.environmentService.args,
|
||||
urisToOpen,
|
||||
forceNewWindow: options.forceNewWindow
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pickFolderAndOpen(options: INativeOpenDialogOptions): void {
|
||||
this.doPickAndOpen(options, true /* pick folders */, false /* pick files */);
|
||||
async pickFolderAndOpen(options: INativeOpenDialogOptions): Promise<void> {
|
||||
const title = localize('openFolder', "Open Folder");
|
||||
const paths = await this.dialogs.pick({ ...options, pickFolders: true, title });
|
||||
if (paths) {
|
||||
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFolder', options.telemetryExtraData);
|
||||
this.open({
|
||||
context: OpenContext.DIALOG,
|
||||
contextWindowId: options.windowId,
|
||||
cli: this.environmentService.args,
|
||||
urisToOpen: paths.map(path => ({ folderUri: URI.file(path) })),
|
||||
forceNewWindow: options.forceNewWindow
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pickFileAndOpen(options: INativeOpenDialogOptions): void {
|
||||
this.doPickAndOpen(options, false /* pick folders */, true /* pick files */);
|
||||
async pickFileAndOpen(options: INativeOpenDialogOptions): Promise<void> {
|
||||
const title = localize('openFile', "Open File");
|
||||
const paths = await this.dialogs.pick({ ...options, pickFiles: true, title });
|
||||
if (paths) {
|
||||
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFile', options.telemetryExtraData);
|
||||
this.open({
|
||||
context: OpenContext.DIALOG,
|
||||
contextWindowId: options.windowId,
|
||||
cli: this.environmentService.args,
|
||||
urisToOpen: paths.map(path => ({ fileUri: URI.file(path) })),
|
||||
forceNewWindow: options.forceNewWindow
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private doPickAndOpen(options: INativeOpenDialogOptions, pickFolders: boolean, pickFiles: boolean): void {
|
||||
const internalOptions = options as IInternalNativeOpenDialogOptions;
|
||||
|
||||
internalOptions.pickFolders = pickFolders;
|
||||
internalOptions.pickFiles = pickFiles;
|
||||
|
||||
const dialogOptions: OpenDialogOptions = internalOptions.dialogOptions || Object.create(null);
|
||||
internalOptions.dialogOptions = dialogOptions;
|
||||
|
||||
if (!internalOptions.dialogOptions.title) {
|
||||
if (pickFolders && pickFiles) {
|
||||
internalOptions.dialogOptions.title = localize('open', "Open");
|
||||
} else if (pickFolders) {
|
||||
internalOptions.dialogOptions.title = localize('openFolder', "Open Folder");
|
||||
} else {
|
||||
internalOptions.dialogOptions.title = localize('openFile', "Open File");
|
||||
}
|
||||
async pickWorkspaceAndOpen(options: INativeOpenDialogOptions): Promise<void> {
|
||||
const title = localize('openWorkspaceTitle', "Open Workspace");
|
||||
const buttonLabel = mnemonicButtonLabel(localize({ key: 'openWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open"));
|
||||
const filters = WORKSPACE_FILTER;
|
||||
const paths = await this.dialogs.pick({ ...options, pickFiles: true, title, filters, buttonLabel });
|
||||
if (paths) {
|
||||
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openWorkspace', options.telemetryExtraData);
|
||||
this.open({
|
||||
context: OpenContext.DIALOG,
|
||||
contextWindowId: options.windowId,
|
||||
cli: this.environmentService.args,
|
||||
urisToOpen: paths.map(path => ({ workspaceUri: URI.file(path) })),
|
||||
forceNewWindow: options.forceNewWindow
|
||||
});
|
||||
}
|
||||
|
||||
if (!internalOptions.telemetryEventName) {
|
||||
if (pickFolders && pickFiles) {
|
||||
// __GDPR__TODO__ classify event
|
||||
internalOptions.telemetryEventName = 'openFileFolder';
|
||||
} else if (pickFolders) {
|
||||
internalOptions.telemetryEventName = 'openFolder';
|
||||
} else {
|
||||
internalOptions.telemetryEventName = 'openFile';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.dialogs.pickAndOpen(internalOptions);
|
||||
private sendPickerTelemetry(paths: string[], telemetryEventName: string, telemetryExtraData?: ITelemetryData) {
|
||||
|
||||
const numberOfPaths = paths ? paths.length : 0;
|
||||
|
||||
// Telemetry
|
||||
// __GDPR__TODO__ Dynamic event names and dynamic properties. Can not be registered statically.
|
||||
this.telemetryService.publicLog(telemetryEventName, {
|
||||
...telemetryExtraData,
|
||||
outcome: numberOfPaths ? 'success' : 'canceled',
|
||||
numberOfPaths
|
||||
});
|
||||
}
|
||||
|
||||
showMessageBox(options: Electron.MessageBoxOptions, win?: ICodeWindow): Promise<IMessageBoxResult> {
|
||||
@@ -1793,65 +1819,42 @@ export class WindowsManager implements IWindowsMainService {
|
||||
}
|
||||
|
||||
interface IInternalNativeOpenDialogOptions extends INativeOpenDialogOptions {
|
||||
|
||||
pickFolders?: boolean;
|
||||
pickFiles?: boolean;
|
||||
|
||||
title: string;
|
||||
buttonLabel?: string;
|
||||
filters?: FileFilter[];
|
||||
}
|
||||
|
||||
class Dialogs {
|
||||
|
||||
private static readonly workingDirPickerStorageKey = 'pickerWorkingDir';
|
||||
|
||||
private readonly mapWindowToDialogQueue: Map<number, Queue<any>>;
|
||||
private readonly noWindowDialogQueue: Queue<any>;
|
||||
private readonly mapWindowToDialogQueue: Map<number, Queue<void>>;
|
||||
private readonly noWindowDialogQueue: Queue<void>;
|
||||
|
||||
constructor(
|
||||
private readonly environmentService: IEnvironmentService,
|
||||
private readonly telemetryService: ITelemetryService,
|
||||
private readonly stateService: IStateService,
|
||||
private readonly windowsMainService: IWindowsMainService,
|
||||
private readonly windowsMainService: IWindowsMainService
|
||||
) {
|
||||
this.mapWindowToDialogQueue = new Map<number, Queue<any>>();
|
||||
this.noWindowDialogQueue = new Queue<any>();
|
||||
this.mapWindowToDialogQueue = new Map<number, Queue<void>>();
|
||||
this.noWindowDialogQueue = new Queue<void>();
|
||||
}
|
||||
|
||||
pickAndOpen(options: INativeOpenDialogOptions): void {
|
||||
this.getFileOrFolderUris(options).then(paths => {
|
||||
const numberOfPaths = paths ? paths.length : 0;
|
||||
|
||||
// Telemetry
|
||||
if (options.telemetryEventName) {
|
||||
// __GDPR__TODO__ Dynamic event names and dynamic properties. Can not be registered statically.
|
||||
this.telemetryService.publicLog(options.telemetryEventName, {
|
||||
...options.telemetryExtraData,
|
||||
outcome: numberOfPaths ? 'success' : 'canceled',
|
||||
numberOfPaths
|
||||
});
|
||||
}
|
||||
|
||||
// Open
|
||||
if (numberOfPaths) {
|
||||
this.windowsMainService.open({
|
||||
context: OpenContext.DIALOG,
|
||||
contextWindowId: options.windowId,
|
||||
cli: this.environmentService.args,
|
||||
urisToOpen: paths,
|
||||
forceNewWindow: options.forceNewWindow,
|
||||
forceOpenWorkspaceAsFile: options.dialogOptions && !equals(options.dialogOptions.filters, WORKSPACE_FILTER)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getFileOrFolderUris(options: IInternalNativeOpenDialogOptions): Promise<IURIToOpen[] | undefined> {
|
||||
pick(options: IInternalNativeOpenDialogOptions): Promise<string[] | undefined> {
|
||||
|
||||
// Ensure dialog options
|
||||
const dialogOptions = options.dialogOptions || Object.create(null);
|
||||
options.dialogOptions = dialogOptions;
|
||||
const dialogOptions: Electron.OpenDialogOptions = {
|
||||
title: options.title,
|
||||
buttonLabel: options.buttonLabel,
|
||||
filters: options.filters
|
||||
};
|
||||
|
||||
// Ensure defaultPath
|
||||
if (!dialogOptions.defaultPath) {
|
||||
dialogOptions.defaultPath = this.stateService.getItem<string>(Dialogs.workingDirPickerStorageKey);
|
||||
}
|
||||
dialogOptions.defaultPath = options.defaultPath || this.stateService.getItem<string>(Dialogs.workingDirPickerStorageKey);
|
||||
|
||||
|
||||
// Ensure properties
|
||||
if (typeof options.pickFiles === 'boolean' || typeof options.pickFolders === 'boolean') {
|
||||
@@ -1878,13 +1881,7 @@ class Dialogs {
|
||||
|
||||
// Remember path in storage for next time
|
||||
this.stateService.setItem(Dialogs.workingDirPickerStorageKey, dirname(paths[0]));
|
||||
|
||||
const result: IURIToOpen[] = [];
|
||||
for (const path of paths) {
|
||||
result.push({ uri: URI.file(path) });
|
||||
}
|
||||
|
||||
return result;
|
||||
return paths;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -2057,21 +2054,13 @@ class WorkspacesManager {
|
||||
return { workspace, backupPath };
|
||||
}
|
||||
|
||||
pickWorkspaceAndOpen(options: INativeOpenDialogOptions): void {
|
||||
const window = (typeof options.windowId === 'number' ? this.windowsMainService.getWindowById(options.windowId) : undefined) || this.windowsMainService.getFocusedWindow() || this.windowsMainService.getLastActiveWindow();
|
||||
|
||||
this.windowsMainService.pickFileAndOpen({
|
||||
windowId: window ? window.id : undefined,
|
||||
dialogOptions: {
|
||||
buttonLabel: mnemonicButtonLabel(localize({ key: 'openWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open")),
|
||||
title: localize('openWorkspaceTitle', "Open Workspace"),
|
||||
filters: WORKSPACE_FILTER,
|
||||
properties: ['openFile'],
|
||||
defaultPath: options.dialogOptions && options.dialogOptions.defaultPath
|
||||
},
|
||||
forceNewWindow: options.forceNewWindow,
|
||||
telemetryEventName: options.telemetryEventName,
|
||||
telemetryExtraData: options.telemetryExtraData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function resourceFromURIToOpen(u: IURIToOpen) {
|
||||
if (isWorkspaceToOpen(u)) {
|
||||
return u.workspaceUri;
|
||||
} else if (isFolderToOpen(u)) {
|
||||
return u.folderUri;
|
||||
}
|
||||
return u.fileUri;
|
||||
}
|
||||
Reference in New Issue
Block a user