mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 09:35:39 -05:00
Merge VS Code 1.31.1 (#4283)
This commit is contained in:
@@ -13,7 +13,7 @@ import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/
|
||||
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, app } from 'electron';
|
||||
import { ipcMain as ipc, screen, BrowserWindow, dialog, systemPreferences } from 'electron';
|
||||
import { IPathWithLineAndColumn, parseLineAndColumnAware } from 'vs/code/node/paths';
|
||||
import { ILifecycleService, UnloadReason, IWindowUnloadEvent, LifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -26,8 +26,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
|
||||
import { IHistoryMainService } from 'vs/platform/history/common/history';
|
||||
import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IWorkspacesMainService, IWorkspaceIdentifier, WORKSPACE_FILTER, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspacesMainService, IWorkspaceIdentifier, WORKSPACE_FILTER, ISingleFolderWorkspaceIdentifier, 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';
|
||||
@@ -35,7 +34,7 @@ import { normalizeNFC } from 'vs/base/common/normalization';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Queue, timeout } from 'vs/base/common/async';
|
||||
import { exists } from 'vs/base/node/pfs';
|
||||
import { getComparisonKey, isEqual, normalizePath } from 'vs/base/common/resources';
|
||||
import { getComparisonKey, isEqual, normalizePath, basename as resourcesBasename } from 'vs/base/common/resources';
|
||||
import { endsWith } from 'vs/base/common/strings';
|
||||
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
@@ -146,27 +145,21 @@ export class WindowsManager implements IWindowsMainService {
|
||||
private _onWindowLoad = new Emitter<number>();
|
||||
onWindowLoad: CommonEvent<number> = this._onWindowLoad.event;
|
||||
|
||||
private _onActiveWindowChanged = new Emitter<ICodeWindow>();
|
||||
onActiveWindowChanged: CommonEvent<ICodeWindow> = this._onActiveWindowChanged.event;
|
||||
|
||||
private _onWindowReload = new Emitter<number>();
|
||||
onWindowReload: CommonEvent<number> = this._onWindowReload.event;
|
||||
|
||||
private _onWindowsCountChanged = new Emitter<IWindowsCountChangedEvent>();
|
||||
onWindowsCountChanged: CommonEvent<IWindowsCountChangedEvent> = this._onWindowsCountChanged.event;
|
||||
|
||||
constructor(
|
||||
private readonly machineId: string,
|
||||
@ILogService private logService: ILogService,
|
||||
@IStateService private stateService: IStateService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@ILifecycleService private lifecycleService: ILifecycleService,
|
||||
@IBackupMainService private backupMainService: IBackupMainService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IHistoryMainService private historyMainService: IHistoryMainService,
|
||||
@IWorkspacesMainService private workspacesMainService: IWorkspacesMainService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IStateService private readonly stateService: IStateService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IBackupMainService private readonly backupMainService: IBackupMainService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IHistoryMainService private readonly historyMainService: IHistoryMainService,
|
||||
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
this.windowsState = this.getWindowsState();
|
||||
if (!Array.isArray(this.windowsState.openedWindows)) {
|
||||
@@ -174,7 +167,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
}
|
||||
|
||||
this.dialogs = new Dialogs(environmentService, telemetryService, stateService, this);
|
||||
this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, environmentService, this);
|
||||
this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, environmentService, historyMainService, this);
|
||||
}
|
||||
|
||||
private getWindowsState(): IWindowsState {
|
||||
@@ -209,13 +202,6 @@ export class WindowsManager implements IWindowsMainService {
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// React to windows focus changes
|
||||
app.on('browser-window-focus', () => {
|
||||
setTimeout(() => {
|
||||
this._onActiveWindowChanged.fire(this.getLastActiveWindow());
|
||||
});
|
||||
});
|
||||
|
||||
// React to workbench ready events from windows
|
||||
ipc.on('vscode:workbenchReady', (event: any, windowId: number) => {
|
||||
this.logService.trace('IPC#vscode-workbenchReady');
|
||||
@@ -249,7 +235,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
// clear last closed window state when a new window opens. this helps on macOS where
|
||||
// otherwise closing the last window, opening a new window and then quitting would
|
||||
// use the state of the previously closed window when restarting.
|
||||
this.lastClosedWindowState = void 0;
|
||||
this.lastClosedWindowState = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -387,7 +373,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
}
|
||||
|
||||
// collect all file inputs
|
||||
let fileInputs: IFileInputs = void 0;
|
||||
let fileInputs: IFileInputs = undefined;
|
||||
for (const path of pathsToOpen) {
|
||||
if (path.fileUri) {
|
||||
if (!fileInputs) {
|
||||
@@ -492,8 +478,8 @@ export class WindowsManager implements IWindowsMainService {
|
||||
|
||||
// Remember in recent document list (unless this opens for extension development)
|
||||
// Also do not add paths when files are opened for diffing, only if opened individually
|
||||
if (!usedWindows.some(w => w.isExtensionDevelopmentHost) && !openConfig.cli.diff) {
|
||||
const recentlyOpenedWorkspaces: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier)[] = [];
|
||||
if (!usedWindows.some(w => w.isExtensionDevelopmentHost) && !openConfig.diffMode) {
|
||||
const recentlyOpenedWorkspaces: Array<IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier> = [];
|
||||
const recentlyOpenedFiles: URI[] = [];
|
||||
|
||||
pathsToOpen.forEach(win => {
|
||||
@@ -513,7 +499,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
// used for the edit operation is closed or loaded to a different folder so that the waiting
|
||||
// process can continue. We do this by deleting the waitMarkerFilePath.
|
||||
if (openConfig.context === OpenContext.CLI && openConfig.cli.wait && openConfig.cli.waitMarkerFilePath && usedWindows.length === 1 && usedWindows[0]) {
|
||||
this.waitForWindowCloseOrLoad(usedWindows[0].id).then(() => fs.unlink(openConfig.cli.waitMarkerFilePath, error => void 0));
|
||||
this.waitForWindowCloseOrLoad(usedWindows[0].id).then(() => fs.unlink(openConfig.cli.waitMarkerFilePath, error => undefined));
|
||||
}
|
||||
|
||||
return usedWindows;
|
||||
@@ -552,9 +538,6 @@ export class WindowsManager implements IWindowsMainService {
|
||||
if (lastActiveWindow) {
|
||||
usedWindows.push(this.doAddFoldersToExistingWindow(lastActiveWindow, foldersToAdd));
|
||||
}
|
||||
|
||||
// Reset because we handled them
|
||||
foldersToAdd = [];
|
||||
}
|
||||
|
||||
// Handle files to open/diff or to create when we dont open a folder and we do not restore any folder/untitled from hot-exit
|
||||
@@ -595,7 +578,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
usedWindows.push(this.doOpenFilesInExistingWindow(openConfig, bestWindowOrFolder, fileInputs));
|
||||
|
||||
// Reset these because we handled them
|
||||
fileInputs = void 0;
|
||||
fileInputs = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,7 +595,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
}));
|
||||
|
||||
// Reset these because we handled them
|
||||
fileInputs = void 0;
|
||||
fileInputs = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,14 +607,14 @@ export class WindowsManager implements IWindowsMainService {
|
||||
const windowsOnWorkspace = arrays.coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspace(WindowsManager.WINDOWS, workspaceToOpen)));
|
||||
if (windowsOnWorkspace.length > 0) {
|
||||
const windowOnWorkspace = windowsOnWorkspace[0];
|
||||
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === windowOnWorkspace.remoteAuthority) ? fileInputs : void 0;
|
||||
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === windowOnWorkspace.remoteAuthority) ? fileInputs : undefined;
|
||||
|
||||
// Do open files
|
||||
usedWindows.push(this.doOpenFilesInExistingWindow(openConfig, windowOnWorkspace, fileInputsForWindow));
|
||||
|
||||
// Reset these because we handled them
|
||||
if (fileInputsForWindow) {
|
||||
fileInputs = void 0;
|
||||
fileInputs = undefined;
|
||||
}
|
||||
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
@@ -643,14 +626,14 @@ export class WindowsManager implements IWindowsMainService {
|
||||
return; // ignore folders that are already open
|
||||
}
|
||||
|
||||
const fileInputsForWindow = (fileInputs && !fileInputs.remoteAuthority) ? fileInputs : void 0;
|
||||
const fileInputsForWindow = (fileInputs && !fileInputs.remoteAuthority) ? fileInputs : undefined;
|
||||
|
||||
// Do open folder
|
||||
usedWindows.push(this.doOpenFolderOrWorkspace(openConfig, { workspace: workspaceToOpen }, openFolderInNewWindow, fileInputsForWindow));
|
||||
|
||||
// Reset these because we handled them
|
||||
if (fileInputsForWindow) {
|
||||
fileInputs = void 0;
|
||||
fileInputs = undefined;
|
||||
}
|
||||
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
@@ -666,14 +649,14 @@ export class WindowsManager implements IWindowsMainService {
|
||||
const windowsOnFolderPath = arrays.coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnWorkspace(WindowsManager.WINDOWS, folderToOpen)));
|
||||
if (windowsOnFolderPath.length > 0) {
|
||||
const windowOnFolderPath = windowsOnFolderPath[0];
|
||||
const fileInputsForWindow = fileInputs && fileInputs.remoteAuthority === windowOnFolderPath.remoteAuthority ? fileInputs : void 0;
|
||||
const fileInputsForWindow = fileInputs && fileInputs.remoteAuthority === windowOnFolderPath.remoteAuthority ? fileInputs : undefined;
|
||||
|
||||
// Do open files
|
||||
usedWindows.push(this.doOpenFilesInExistingWindow(openConfig, windowOnFolderPath, fileInputsForWindow));
|
||||
|
||||
// Reset these because we handled them
|
||||
if (fileInputsForWindow) {
|
||||
fileInputs = void 0;
|
||||
fileInputs = undefined;
|
||||
}
|
||||
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
@@ -687,14 +670,14 @@ export class WindowsManager implements IWindowsMainService {
|
||||
}
|
||||
|
||||
const remoteAuthority = getRemoteAuthority(folderToOpen);
|
||||
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === remoteAuthority) ? fileInputs : void 0;
|
||||
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === remoteAuthority) ? fileInputs : undefined;
|
||||
|
||||
// Do open folder
|
||||
usedWindows.push(this.doOpenFolderOrWorkspace(openConfig, { folderUri: folderToOpen, remoteAuthority }, openFolderInNewWindow, fileInputsForWindow));
|
||||
|
||||
// Reset these because we handled them
|
||||
if (fileInputsForWindow) {
|
||||
fileInputs = void 0;
|
||||
fileInputs = undefined;
|
||||
}
|
||||
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
@@ -705,7 +688,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
if (emptyToRestore.length > 0) {
|
||||
emptyToRestore.forEach(emptyWindowBackupInfo => {
|
||||
const remoteAuthority = emptyWindowBackupInfo.remoteAuthority;
|
||||
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === remoteAuthority) ? fileInputs : void 0;
|
||||
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === remoteAuthority) ? fileInputs : undefined;
|
||||
|
||||
usedWindows.push(this.openInBrowserWindow({
|
||||
userEnv: openConfig.userEnv,
|
||||
@@ -720,7 +703,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
|
||||
// Reset these because we handled them
|
||||
if (fileInputsForWindow) {
|
||||
fileInputs = void 0;
|
||||
fileInputs = undefined;
|
||||
}
|
||||
|
||||
openFolderInNewWindow = true; // any other folders to open must open in new window then
|
||||
@@ -732,7 +715,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
if (fileInputs && !emptyToOpen) {
|
||||
emptyToOpen++;
|
||||
}
|
||||
const remoteAuthority = fileInputs ? fileInputs.remoteAuthority : (openConfig.cli && openConfig.cli.remote || void 0);
|
||||
const remoteAuthority = fileInputs ? fileInputs.remoteAuthority : (openConfig.cli && openConfig.cli.remote || undefined);
|
||||
for (let i = 0; i < emptyToOpen; i++) {
|
||||
usedWindows.push(this.openInBrowserWindow({
|
||||
userEnv: openConfig.userEnv,
|
||||
@@ -745,7 +728,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
}));
|
||||
|
||||
// Reset these because we handled them
|
||||
fileInputs = void 0;
|
||||
fileInputs = undefined;
|
||||
openFolderInNewWindow = true; // any other window to open must open in new window then
|
||||
}
|
||||
}
|
||||
@@ -834,8 +817,8 @@ export class WindowsManager implements IWindowsMainService {
|
||||
// folders should be added to the existing window.
|
||||
if (!openConfig.addMode && isCommandLineOrAPICall) {
|
||||
const foldersToOpen = windowsToOpen.filter(path => !!path.folderUri);
|
||||
if (foldersToOpen.length > 1) {
|
||||
const workspace = this.workspacesMainService.createWorkspaceSync(foldersToOpen.map(folder => ({ uri: folder.folderUri })));
|
||||
if (foldersToOpen.length > 1 && foldersToOpen.every(f => f.folderUri.scheme === Schemas.file)) {
|
||||
const workspace = this.workspacesMainService.createUntitledWorkspaceSync(foldersToOpen.map(folder => ({ uri: folder.folderUri })));
|
||||
|
||||
// Add workspace and remove folders thereby
|
||||
windowsToOpen.push({ workspace, remoteAuthority: foldersToOpen[0].remoteAuthority });
|
||||
@@ -886,7 +869,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
|
||||
private doExtractPathsFromCLI(cli: ParsedArgs): IPath[] {
|
||||
const pathsToOpen: IPathToOpen[] = [];
|
||||
const parseOptions: IPathParseOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto, remoteAuthority: cli.remote || void 0 };
|
||||
const parseOptions: IPathParseOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto, remoteAuthority: cli.remote || undefined };
|
||||
|
||||
// folder uris
|
||||
const folderUris = asArray(cli['folder-uri']);
|
||||
@@ -1017,8 +1000,9 @@ export class WindowsManager implements IWindowsMainService {
|
||||
|
||||
// normalize URI
|
||||
uri = normalizePath(uri);
|
||||
if (endsWith(uri.path, '/')) {
|
||||
uri = uri.with({ path: uri.path.substr(0, uri.path.length - 1) });
|
||||
const uriPath = uri.path;
|
||||
if (uriPath.length > 2 && endsWith(uriPath, '/')) {
|
||||
uri = uri.with({ path: uriPath.substr(0, uriPath.length - 1) });
|
||||
}
|
||||
if (isFile) {
|
||||
if (options && options.gotoLineMode) {
|
||||
@@ -1074,8 +1058,8 @@ export class WindowsManager implements IWindowsMainService {
|
||||
// File
|
||||
return {
|
||||
fileUri: URI.file(candidate),
|
||||
lineNumber: gotoLineMode ? parsedPath.line : void 0,
|
||||
columnNumber: gotoLineMode ? parsedPath.column : void 0,
|
||||
lineNumber: gotoLineMode ? parsedPath.line : undefined,
|
||||
columnNumber: gotoLineMode ? parsedPath.column : undefined,
|
||||
remoteAuthority
|
||||
};
|
||||
}
|
||||
@@ -1473,10 +1457,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
// Only reload when the window has not vetoed this
|
||||
this.lifecycleService.unload(win, UnloadReason.RELOAD).then(veto => {
|
||||
if (!veto) {
|
||||
win.reload(void 0, cli);
|
||||
|
||||
// Emit
|
||||
this._onWindowReload.fire(win.id);
|
||||
win.reload(undefined, cli);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1489,18 +1470,10 @@ export class WindowsManager implements IWindowsMainService {
|
||||
});
|
||||
}
|
||||
|
||||
saveAndEnterWorkspace(win: ICodeWindow, path: string): TPromise<IEnterWorkspaceResult> {
|
||||
return this.workspacesManager.saveAndEnterWorkspace(win, path).then(result => this.doEnterWorkspace(win, result));
|
||||
}
|
||||
|
||||
enterWorkspace(win: ICodeWindow, path: string): TPromise<IEnterWorkspaceResult> {
|
||||
enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult> {
|
||||
return this.workspacesManager.enterWorkspace(win, path).then(result => this.doEnterWorkspace(win, result));
|
||||
}
|
||||
|
||||
createAndEnterWorkspace(win: ICodeWindow, folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<IEnterWorkspaceResult> {
|
||||
return this.workspacesManager.createAndEnterWorkspace(win, folders, path).then(result => this.doEnterWorkspace(win, result));
|
||||
}
|
||||
|
||||
private doEnterWorkspace(win: ICodeWindow, result: IEnterWorkspaceResult): IEnterWorkspaceResult {
|
||||
|
||||
// Mark as recently opened
|
||||
@@ -1575,7 +1548,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
|
||||
openNewWindow(context: OpenContext, options?: INewWindowOptions): ICodeWindow[] {
|
||||
let cli = this.environmentService.args;
|
||||
let remote = options && options.remoteAuthority || void 0;
|
||||
let remote = options && options.remoteAuthority || undefined;
|
||||
if (cli && (cli.remote !== remote)) {
|
||||
cli = { ...cli, remote };
|
||||
}
|
||||
@@ -1586,7 +1559,7 @@ export class WindowsManager implements IWindowsMainService {
|
||||
return this.open({ context, cli: this.environmentService.args, forceNewTabbedWindow: true, forceEmpty: true });
|
||||
}
|
||||
|
||||
waitForWindowCloseOrLoad(windowId: number): Thenable<void> {
|
||||
waitForWindowCloseOrLoad(windowId: number): Promise<void> {
|
||||
return new Promise<void>(resolve => {
|
||||
function handler(id: number) {
|
||||
if (id === windowId) {
|
||||
@@ -1658,6 +1631,17 @@ export class WindowsManager implements IWindowsMainService {
|
||||
|
||||
// Unresponsive
|
||||
if (error === WindowError.UNRESPONSIVE) {
|
||||
if (window.isExtensionDevelopmentHost || window.isExtensionTestHost || (window.win && window.win.webContents && window.win.webContents.isDevToolsOpened())) {
|
||||
// TODO@Ben Workaround for https://github.com/Microsoft/vscode/issues/56994
|
||||
// In certain cases the window can report unresponsiveness because a breakpoint was hit
|
||||
// and the process is stopped executing. The most typical cases are:
|
||||
// - devtools are opened and debugging happens
|
||||
// - window is an extensions development host that is being debugged
|
||||
// - window is an extension test development host that is being debugged
|
||||
return;
|
||||
}
|
||||
|
||||
// Show Dialog
|
||||
this.dialogs.showMessageBox({
|
||||
title: product.nameLong,
|
||||
type: 'warning',
|
||||
@@ -1763,15 +1747,15 @@ export class WindowsManager implements IWindowsMainService {
|
||||
this.dialogs.pickAndOpen(internalOptions);
|
||||
}
|
||||
|
||||
showMessageBox(options: Electron.MessageBoxOptions, win?: ICodeWindow): Thenable<IMessageBoxResult> {
|
||||
showMessageBox(options: Electron.MessageBoxOptions, win?: ICodeWindow): Promise<IMessageBoxResult> {
|
||||
return this.dialogs.showMessageBox(options, win);
|
||||
}
|
||||
|
||||
showSaveDialog(options: Electron.SaveDialogOptions, win?: ICodeWindow): Thenable<string> {
|
||||
showSaveDialog(options: Electron.SaveDialogOptions, win?: ICodeWindow): Promise<string> {
|
||||
return this.dialogs.showSaveDialog(options, win);
|
||||
}
|
||||
|
||||
showOpenDialog(options: Electron.OpenDialogOptions, win?: ICodeWindow): Thenable<string[]> {
|
||||
showOpenDialog(options: Electron.OpenDialogOptions, win?: ICodeWindow): Promise<string[]> {
|
||||
return this.dialogs.showOpenDialog(options, win);
|
||||
}
|
||||
|
||||
@@ -1833,6 +1817,7 @@ class Dialogs {
|
||||
if (numberOfPaths) {
|
||||
this.windowsMainService.open({
|
||||
context: OpenContext.DIALOG,
|
||||
contextWindowId: options.windowId,
|
||||
cli: this.environmentService.args,
|
||||
urisToOpen: paths,
|
||||
forceNewWindow: options.forceNewWindow,
|
||||
@@ -1842,7 +1827,7 @@ class Dialogs {
|
||||
});
|
||||
}
|
||||
|
||||
private getFileOrFolderUris(options: IInternalNativeOpenDialogOptions): TPromise<URI[]> {
|
||||
private getFileOrFolderUris(options: IInternalNativeOpenDialogOptions): Promise<URI[]> {
|
||||
|
||||
// Ensure dialog options
|
||||
if (!options.dialogOptions) {
|
||||
@@ -1856,7 +1841,7 @@ class Dialogs {
|
||||
|
||||
// Ensure properties
|
||||
if (typeof options.pickFiles === 'boolean' || typeof options.pickFolders === 'boolean') {
|
||||
options.dialogOptions.properties = void 0; // let it override based on the booleans
|
||||
options.dialogOptions.properties = undefined; // let it override based on the booleans
|
||||
|
||||
if (options.pickFiles && options.pickFolders) {
|
||||
options.dialogOptions.properties = ['multiSelections', 'openDirectory', 'openFile', 'createDirectory'];
|
||||
@@ -1883,7 +1868,7 @@ class Dialogs {
|
||||
return paths.map(path => URI.file(path));
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1901,17 +1886,17 @@ class Dialogs {
|
||||
return windowDialogQueue;
|
||||
}
|
||||
|
||||
showMessageBox(options: Electron.MessageBoxOptions, window?: ICodeWindow): Thenable<IMessageBoxResult> {
|
||||
showMessageBox(options: Electron.MessageBoxOptions, window?: ICodeWindow): Promise<IMessageBoxResult> {
|
||||
return this.getDialogQueue(window).queue(() => {
|
||||
return new Promise(resolve => {
|
||||
dialog.showMessageBox(window ? window.win : void 0, options, (response: number, checkboxChecked: boolean) => {
|
||||
dialog.showMessageBox(window ? window.win : undefined, options, (response: number, checkboxChecked: boolean) => {
|
||||
resolve({ button: response, checkboxChecked });
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
showSaveDialog(options: Electron.SaveDialogOptions, window?: ICodeWindow): Thenable<string> {
|
||||
showSaveDialog(options: Electron.SaveDialogOptions, window?: ICodeWindow): Promise<string> {
|
||||
|
||||
function normalizePath(path: string): string {
|
||||
if (path && isMacintosh) {
|
||||
@@ -1923,14 +1908,14 @@ class Dialogs {
|
||||
|
||||
return this.getDialogQueue(window).queue(() => {
|
||||
return new Promise(resolve => {
|
||||
dialog.showSaveDialog(window ? window.win : void 0, options, path => {
|
||||
dialog.showSaveDialog(window ? window.win : undefined, options, path => {
|
||||
resolve(normalizePath(path));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
showOpenDialog(options: Electron.OpenDialogOptions, window?: ICodeWindow): Thenable<string[]> {
|
||||
showOpenDialog(options: Electron.OpenDialogOptions, window?: ICodeWindow): Promise<string[]> {
|
||||
|
||||
function normalizePaths(paths: string[]): string[] {
|
||||
if (paths && paths.length > 0 && isMacintosh) {
|
||||
@@ -1948,14 +1933,14 @@ class Dialogs {
|
||||
if (options.defaultPath) {
|
||||
validatePathPromise = exists(options.defaultPath).then(exists => {
|
||||
if (!exists) {
|
||||
options.defaultPath = void 0;
|
||||
options.defaultPath = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Show dialog and wrap as promise
|
||||
validatePathPromise.then(() => {
|
||||
dialog.showOpenDialog(window ? window.win : void 0, options, paths => {
|
||||
dialog.showOpenDialog(window ? window.win : undefined, options, paths => {
|
||||
resolve(normalizePaths(paths));
|
||||
});
|
||||
});
|
||||
@@ -1970,68 +1955,42 @@ class WorkspacesManager {
|
||||
private workspacesMainService: IWorkspacesMainService,
|
||||
private backupMainService: IBackupMainService,
|
||||
private environmentService: IEnvironmentService,
|
||||
private windowsMainService: IWindowsMainService
|
||||
private historyMainService: IHistoryMainService,
|
||||
private windowsMainService: IWindowsMainService,
|
||||
) {
|
||||
}
|
||||
|
||||
saveAndEnterWorkspace(window: ICodeWindow, path: string): TPromise<IEnterWorkspaceResult> {
|
||||
if (!window || !window.win || !window.isReady || !window.openedWorkspace || !path || !this.isValidTargetWorkspacePath(window, path)) {
|
||||
return TPromise.as(null); // return early if the window is not ready or disposed or does not have a workspace
|
||||
}
|
||||
|
||||
return this.doSaveAndOpenWorkspace(window, window.openedWorkspace, path);
|
||||
}
|
||||
|
||||
enterWorkspace(window: ICodeWindow, path: string): TPromise<IEnterWorkspaceResult> {
|
||||
enterWorkspace(window: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | null> {
|
||||
if (!window || !window.win || !window.isReady) {
|
||||
return TPromise.as(null); // return early if the window is not ready or disposed
|
||||
return Promise.resolve(null); // return early if the window is not ready or disposed
|
||||
}
|
||||
|
||||
return this.isValidTargetWorkspacePath(window, path).then(isValid => {
|
||||
if (!isValid) {
|
||||
return TPromise.as<IEnterWorkspaceResult>(null); // return early if the workspace is not valid
|
||||
return null; // return early if the workspace is not valid
|
||||
}
|
||||
|
||||
return this.workspacesMainService.resolveWorkspace(path).then(workspace => {
|
||||
return this.doOpenWorkspace(window, workspace);
|
||||
});
|
||||
const workspaceIdentifier = this.workspacesMainService.getWorkspaceIdentifier(path);
|
||||
return this.doOpenWorkspace(window, workspaceIdentifier);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
createAndEnterWorkspace(window: ICodeWindow, folders?: IWorkspaceFolderCreationData[], path?: string): TPromise<IEnterWorkspaceResult> {
|
||||
if (!window || !window.win || !window.isReady) {
|
||||
return TPromise.as(null); // return early if the window is not ready or disposed
|
||||
}
|
||||
|
||||
return this.isValidTargetWorkspacePath(window, path).then(isValid => {
|
||||
if (!isValid) {
|
||||
return TPromise.as(null); // return early if the workspace is not valid
|
||||
}
|
||||
|
||||
return this.workspacesMainService.createWorkspace(folders).then(workspace => {
|
||||
return this.doSaveAndOpenWorkspace(window, workspace, path);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private isValidTargetWorkspacePath(window: ICodeWindow, path?: string): TPromise<boolean> {
|
||||
private isValidTargetWorkspacePath(window: ICodeWindow, path?: URI): Promise<boolean> {
|
||||
if (!path) {
|
||||
return TPromise.wrap(true);
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
if (window.openedWorkspace && window.openedWorkspace.configPath === path) {
|
||||
return TPromise.wrap(false); // window is already opened on a workspace with that path
|
||||
if (window.openedWorkspace && isEqual(URI.file(window.openedWorkspace.configPath), path)) {
|
||||
return Promise.resolve(false); // window is already opened on a workspace with that path
|
||||
}
|
||||
|
||||
// Prevent overwriting a workspace that is currently opened in another window
|
||||
if (findWindowOnWorkspace(this.windowsMainService.getWindows(), { id: this.workspacesMainService.getWorkspaceId(path), configPath: path })) {
|
||||
if (findWindowOnWorkspace(this.windowsMainService.getWindows(), this.workspacesMainService.getWorkspaceIdentifier(path))) {
|
||||
const options: Electron.MessageBoxOptions = {
|
||||
title: product.nameLong,
|
||||
type: 'info',
|
||||
buttons: [localize('ok', "OK")],
|
||||
message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", basename(path)),
|
||||
message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", resourcesBasename(path)),
|
||||
detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again."),
|
||||
noLink: true
|
||||
};
|
||||
@@ -2039,18 +1998,7 @@ class WorkspacesManager {
|
||||
return this.windowsMainService.showMessageBox(options, this.windowsMainService.getFocusedWindow()).then(() => false);
|
||||
}
|
||||
|
||||
return TPromise.wrap(true); // OK
|
||||
}
|
||||
|
||||
private doSaveAndOpenWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier, path?: string): TPromise<IEnterWorkspaceResult> {
|
||||
let savePromise: TPromise<IWorkspaceIdentifier>;
|
||||
if (path) {
|
||||
savePromise = this.workspacesMainService.saveWorkspace(workspace, path);
|
||||
} else {
|
||||
savePromise = TPromise.as(workspace);
|
||||
}
|
||||
|
||||
return savePromise.then(workspace => this.doOpenWorkspace(window, workspace));
|
||||
return Promise.resolve(true); // OK
|
||||
}
|
||||
|
||||
private doOpenWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): IEnterWorkspaceResult {
|
||||
@@ -2062,8 +2010,13 @@ class WorkspacesManager {
|
||||
backupPath = this.backupMainService.registerWorkspaceBackupSync(workspace, window.config.backupPath);
|
||||
}
|
||||
|
||||
// if the window was opened on an untitled workspace, delete it.
|
||||
if (window.openedWorkspace && this.workspacesMainService.isUntitledWorkspace(window.openedWorkspace)) {
|
||||
this.workspacesMainService.deleteUntitledWorkspaceSync(window.openedWorkspace);
|
||||
}
|
||||
|
||||
// Update window configuration properly based on transition to workspace
|
||||
window.config.folderUri = void 0;
|
||||
window.config.folderUri = undefined;
|
||||
window.config.workspace = workspace;
|
||||
window.config.backupPath = backupPath;
|
||||
|
||||
@@ -2074,7 +2027,7 @@ class WorkspacesManager {
|
||||
const window = this.windowsMainService.getWindowById(options.windowId) || this.windowsMainService.getFocusedWindow() || this.windowsMainService.getLastActiveWindow();
|
||||
|
||||
this.windowsMainService.pickFileAndOpen({
|
||||
windowId: window ? window.id : void 0,
|
||||
windowId: window ? window.id : undefined,
|
||||
dialogOptions: {
|
||||
buttonLabel: mnemonicButtonLabel(localize({ key: 'openWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open")),
|
||||
title: localize('openWorkspaceTitle', "Open Workspace"),
|
||||
@@ -2088,7 +2041,7 @@ class WorkspacesManager {
|
||||
});
|
||||
}
|
||||
|
||||
promptToSaveUntitledWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): TPromise<boolean> {
|
||||
promptToSaveUntitledWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): Promise<boolean> {
|
||||
enum ConfirmResult {
|
||||
SAVE,
|
||||
DONT_SAVE,
|
||||
@@ -2143,7 +2096,11 @@ class WorkspacesManager {
|
||||
defaultPath: this.getUntitledWorkspaceSaveDialogDefaultPath(workspace)
|
||||
}, window).then(target => {
|
||||
if (target) {
|
||||
return this.workspacesMainService.saveWorkspace(workspace, target).then(() => false, () => false);
|
||||
return this.workspacesMainService.saveWorkspaceAs(workspace, target).then(savedWorkspace => {
|
||||
this.historyMainService.addRecentlyOpened([savedWorkspace], []);
|
||||
this.workspacesMainService.deleteUntitledWorkspaceSync(workspace);
|
||||
return false;
|
||||
}, () => false);
|
||||
}
|
||||
|
||||
return true; // keep veto if no target was provided
|
||||
@@ -2156,7 +2113,7 @@ class WorkspacesManager {
|
||||
private getUntitledWorkspaceSaveDialogDefaultPath(workspace?: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier): string {
|
||||
if (workspace) {
|
||||
if (isSingleFolderWorkspaceIdentifier(workspace)) {
|
||||
return workspace.scheme === Schemas.file ? dirname(workspace.fsPath) : void 0;
|
||||
return workspace.scheme === Schemas.file ? dirname(workspace.fsPath) : undefined;
|
||||
}
|
||||
|
||||
const resolvedWorkspace = this.workspacesMainService.resolveWorkspaceSync(workspace.configPath);
|
||||
@@ -2169,6 +2126,6 @@ class WorkspacesManager {
|
||||
}
|
||||
}
|
||||
|
||||
return void 0;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user