main.ts 6.7 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

8
import nls = require('vs/nls');
J
Johannes Rieken 已提交
9 10 11
import { TPromise } from 'vs/base/common/winjs.base';
import { WorkbenchShell } from 'vs/workbench/electron-browser/shell';
import { IOptions } from 'vs/workbench/common/options';
12
import * as browser from 'vs/base/browser/browser';
J
Johannes Rieken 已提交
13
import { domContentLoaded } from 'vs/base/browser/dom';
E
Erich Gamma 已提交
14
import errors = require('vs/base/common/errors');
15
import comparer = require('vs/base/common/comparers');
E
Erich Gamma 已提交
16 17 18 19
import platform = require('vs/base/common/platform');
import paths = require('vs/base/common/paths');
import uri from 'vs/base/common/uri';
import strings = require('vs/base/common/strings');
J
Johannes Rieken 已提交
20
import { IResourceInput } from 'vs/platform/editor/common/editor';
21 22
import { Workspace } from 'vs/platform/workspace/common/workspace';
import { WorkspaceService } from 'vs/workbench/services/configuration/node/configuration';
B
Benjamin Pasero 已提交
23
import { realpath, stat } from 'vs/base/node/pfs';
J
Johannes Rieken 已提交
24
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
E
Erich Gamma 已提交
25 26
import path = require('path');
import gracefulFs = require('graceful-fs');
B
Benjamin Pasero 已提交
27 28
import { IInitData } from 'vs/workbench/services/timer/common/timerService';
import { TimerService } from 'vs/workbench/services/timer/node/timerService';
A
Alex Dima 已提交
29
import { KeyboardMapperFactory } from "vs/workbench/services/keybinding/electron-browser/keybindingService";
30
import { IWindowConfiguration, IPath } from "vs/platform/windows/common/windows";
B
Benjamin Pasero 已提交
31

32 33
import { webFrame } from 'electron';

B
Benjamin Pasero 已提交
34
import fs = require('fs');
B
Benjamin Pasero 已提交
35
gracefulFs.gracefulify(fs); // enable gracefulFs
E
Erich Gamma 已提交
36

37
export function startup(configuration: IWindowConfiguration): TPromise<void> {
38

39 40
	// Ensure others can listen to zoom level changes
	browser.setZoomFactor(webFrame.getZoomFactor());
41

42 43
	// See https://github.com/Microsoft/vscode/issues/26151
	// Can be trusted because we are not setting it ourselves.
44
	browser.setZoomLevel(webFrame.getZoomLevel(), true /* isTrusted */);
45

46 47
	browser.setFullscreen(!!configuration.fullscreen);

A
Alex Dima 已提交
48 49
	KeyboardMapperFactory.INSTANCE._onKeyboardLayoutChanged(configuration.isISOKeyboard);

50
	browser.setAccessibilitySupport(configuration.accessibilitySupport ? platform.AccessibilitySupport.Enabled : platform.AccessibilitySupport.Disabled);
51

52 53 54
	// Setup Intl
	comparer.setFileNameComparer(new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }));

E
Erich Gamma 已提交
55
	// Shell Options
B
polish  
Benjamin Pasero 已提交
56 57 58
	const filesToOpen = configuration.filesToOpen && configuration.filesToOpen.length ? toInputs(configuration.filesToOpen) : null;
	const filesToCreate = configuration.filesToCreate && configuration.filesToCreate.length ? toInputs(configuration.filesToCreate) : null;
	const filesToDiff = configuration.filesToDiff && configuration.filesToDiff.length ? toInputs(configuration.filesToDiff) : null;
B
Benjamin Pasero 已提交
59
	const shellOptions: IOptions = {
60 61
		filesToOpen,
		filesToCreate,
B
Benjamin Pasero 已提交
62
		filesToDiff
E
Erich Gamma 已提交
63 64
	};

65 66 67 68 69 70
	// Resolve workspace
	return getWorkspace(configuration.workspacePath).then(workspace => {

		// Open workbench
		return openWorkbench(configuration, workspace, shellOptions);
	});
E
Erich Gamma 已提交
71 72
}

73
function toInputs(paths: IPath[], isUntitledFile?: boolean): IResourceInput[] {
E
Erich Gamma 已提交
74
	return paths.map(p => {
75 76 77 78 79 80 81
		const input = <IResourceInput>{};

		if (isUntitledFile) {
			input.resource = uri.from({ scheme: 'untitled', path: p.filePath });
		} else {
			input.resource = uri.file(p.filePath);
		}
E
Erich Gamma 已提交
82

83 84 85 86
		input.options = {
			pinned: true // opening on startup is always pinned and not preview
		};

E
Erich Gamma 已提交
87
		if (p.lineNumber) {
88 89 90
			input.options.selection = {
				startLineNumber: p.lineNumber,
				startColumn: p.columnNumber
E
Erich Gamma 已提交
91 92 93 94 95 96 97
			};
		}

		return input;
	});
}

98
function getWorkspace(workspacePath: string): TPromise<Workspace> {
B
polish  
Benjamin Pasero 已提交
99
	if (!workspacePath) {
100
		return TPromise.as(null);
E
Erich Gamma 已提交
101 102
	}

103 104
	return realpath(workspacePath).then(realWorkspacePath => {

E
Erich Gamma 已提交
105 106 107 108
		// for some weird reason, node adds a trailing slash to UNC paths
		// we never ever want trailing slashes as our workspace path unless
		// someone opens root ("/").
		// See also https://github.com/nodejs/io.js/issues/1765
109 110 111
		if (paths.isUNC(realWorkspacePath) && strings.endsWith(realWorkspacePath, paths.nativeSep)) {
			realWorkspacePath = strings.rtrim(realWorkspacePath, paths.nativeSep);
		}
E
Erich Gamma 已提交
112

113 114
		const workspaceResource = uri.file(realWorkspacePath);
		const folderName = path.basename(realWorkspacePath) || realWorkspacePath;
E
Erich Gamma 已提交
115

B
Benjamin Pasero 已提交
116
		return stat(realWorkspacePath).then(folderStat => {
117 118 119 120 121
			return new Workspace(
				workspaceResource,
				platform.isLinux ? folderStat.ino : folderStat.birthtime.getTime(),
				folderName // On Linux, birthtime is ctime, so we cannot use it! We use the ino instead!
			);
B
Benjamin Pasero 已提交
122
		});
123
	}, error => {
124 125 126 127
		errors.onUnexpectedError(error);

		return null; // treat invalid paths as empty workspace
	});
E
Erich Gamma 已提交
128 129
}

130 131
function openWorkbench(configuration: IWindowConfiguration, workspace: Workspace, options: IOptions): TPromise<void> {
	const environmentService = new EnvironmentService(configuration, configuration.execPath);
132 133
	const workspaceService = new WorkspaceService(environmentService, workspace);
	const timerService = new TimerService((<any>window).MonacoEnvironment.timers as IInitData, !workspaceService.hasWorkspace());
134 135 136

	// Since the configuration service is one of the core services that is used in so many places, we initialize it
	// right before startup of the workbench shell to have its data ready for consumers
137
	return workspaceService.initialize().then(() => {
138
		timerService.beforeDOMContentLoaded = Date.now();
139

A
Alex Dima 已提交
140
		return domContentLoaded().then(() => {
141
			timerService.afterDOMContentLoaded = Date.now();
142 143

			// Open Shell
144
			timerService.beforeWorkbenchOpen = Date.now();
145
			const shell = new WorkbenchShell(document.body, {
146 147
				contextService: workspaceService,
				configurationService: workspaceService,
B
Benjamin Pasero 已提交
148 149
				environmentService,
				timerService
150
			}, configuration, options);
151 152 153 154 155 156
			shell.open();

			// Inform user about loading issues from the loader
			(<any>self).require.config({
				onError: (err: any) => {
					if (err.errorCode === 'load') {
157
						shell.onUnexpectedError(loaderError(err));
158
					}
E
Erich Gamma 已提交
159
				}
160
			});
A
Alex Dima 已提交
161
		});
162
	});
163 164 165 166 167 168 169 170
}

function loaderError(err: Error): Error {
	if (platform.isWeb) {
		return new Error(nls.localize('loaderError', "Failed to load a required file. Either you are no longer connected to the internet or the server you are connected to is offline. Please refresh the browser to try again."));
	}

	return new Error(nls.localize('loaderErrorNative', "Failed to load a required file. Please restart the application to try again. Details: {0}", JSON.stringify(err)));
171
}