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

J
Joao Moreno 已提交
6
import 'vs/css!./media/extensionActions';
J
Joao Moreno 已提交
7
import { localize } from 'vs/nls';
J
Joao Moreno 已提交
8
import { TPromise } from 'vs/base/common/winjs.base';
E
Erich Gamma 已提交
9
import { Action } from 'vs/base/common/actions';
10
import severity from 'vs/base/common/severity';
11
import paths = require('vs/base/common/paths');
J
Joao Moreno 已提交
12
import Event from 'vs/base/common/event';
J
Joao Moreno 已提交
13
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
J
Joao Moreno 已提交
14
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
J
Joao Moreno 已提交
15
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, ConfigurationKey } from './extensions';
16
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
17
import { IMessageService, LaterAction } from 'vs/platform/message/common/message';
18
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
19 20 21
import { ToggleViewletAction } from 'vs/workbench/browser/viewlet';
import { IViewletService } from 'vs/workbench/services/viewlet/common/viewletService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
J
Joao Moreno 已提交
22
import { Query } from '../common/extensionQuery';
J
Joao Moreno 已提交
23
import { shell, remote } from 'electron';
J
Joao Moreno 已提交
24 25 26 27
import { InitialContent } from 'vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate';
import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import URI from 'vs/base/common/uri';
J
Joao Moreno 已提交
28 29

const dialog = remote.dialog;
J
Joao Moreno 已提交
30

31 32
export class InstallAction extends Action {

J
Joao Moreno 已提交
33 34
	private static InstallLabel = localize('installAction', "Install");
	private static InstallingLabel = localize('installing', "Installing");
J
Joao Moreno 已提交
35
	private disposables: IDisposable[] = [];
J
Joao Moreno 已提交
36 37 38
	private _extension: IExtension;
	get extension(): IExtension { return this._extension; }
	set extension(extension: IExtension) { this._extension = extension; this.update(); }
39

40 41 42
	constructor(
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
	) {
J
Joao Moreno 已提交
43
		super('extensions.install', InstallAction.InstallLabel, 'extension-action install', false);
44

45
		this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
J
Joao Moreno 已提交
46
		this.update();
47 48
	}

J
Joao Moreno 已提交
49
	private update(): void {
J
Joao Moreno 已提交
50 51 52 53 54 55
		if (!this.extension) {
			this.enabled = false;
			this.label = InstallAction.InstallLabel;
			return;
		}

56
		this.enabled = this.extensionsWorkbenchService.canInstall(this.extension) && this.extension.state === ExtensionState.Uninstalled;
J
Joao Moreno 已提交
57
		this.label = this.extension.state === ExtensionState.Installing ? InstallAction.InstallingLabel : InstallAction.InstallLabel;
58 59
	}

J
Joao Moreno 已提交
60
	run(): TPromise<any> {
61
		return this.extensionsWorkbenchService.install(this.extension);
62 63
	}

J
Joao Moreno 已提交
64 65 66
	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
67 68
	}
}
J
Joao Moreno 已提交
69

J
Joao Moreno 已提交
70
export class UninstallAction extends Action {
J
Joao Moreno 已提交
71

J
Joao Moreno 已提交
72
	private disposables: IDisposable[] = [];
J
Joao Moreno 已提交
73 74 75
	private _extension: IExtension;
	get extension(): IExtension { return this._extension; }
	set extension(extension: IExtension) { this._extension = extension; this.update(); }
J
Joao Moreno 已提交
76

77
	constructor(
78 79 80
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
		@IMessageService private messageService: IMessageService,
		@IInstantiationService private instantiationService: IInstantiationService
81
	) {
J
Joao Moreno 已提交
82
		super('extensions.uninstall', localize('uninstall', "Uninstall"), 'extension-action uninstall', false);
J
Joao Moreno 已提交
83

J
Joao Moreno 已提交
84 85
		this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
		this.update();
J
Joao Moreno 已提交
86
	}
J
Joao Moreno 已提交
87

J
Joao Moreno 已提交
88 89 90 91 92 93
	private update(): void {
		if (!this.extension) {
			this.enabled = false;
			return;
		}

J
Joao Moreno 已提交
94 95
		this.enabled = this.extension.state === ExtensionState.Installed
			|| this.extension.state === ExtensionState.NeedsRestart;
J
Joao Moreno 已提交
96
	}
J
Joao Moreno 已提交
97

J
Joao Moreno 已提交
98
	run(): TPromise<any> {
J
Joao Moreno 已提交
99
		if (!window.confirm(localize('deleteSure', "Are you sure you want to uninstall '{0}'?", this.extension.displayName))) {
J
Joao Moreno 已提交
100 101
			return TPromise.as(null);
		}
J
Joao Moreno 已提交
102

103 104 105
		return this.extensionsWorkbenchService.uninstall(this.extension).then(() => {
			this.messageService.show(severity.Info, {
				message: localize('postUninstallMessage', "{0} was successfully uninstalled. Restart to deactivate it.", this.extension.displayName),
106
				actions: [this.instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, localize('restartNow', "Restart Now")), LaterAction]
107 108
			});
		});
J
Joao Moreno 已提交
109
	}
J
Joao Moreno 已提交
110

J
Joao Moreno 已提交
111 112 113 114 115
	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
	}
}
J
Joao Moreno 已提交
116 117 118

export class CombinedInstallAction extends Action {

J
Joao Moreno 已提交
119
	private static NoExtensionClass = 'extension-action install no-extension';
J
Joao Moreno 已提交
120 121 122
	private installAction: InstallAction;
	private uninstallAction: UninstallAction;
	private disposables: IDisposable[] = [];
J
Joao Moreno 已提交
123 124 125 126 127 128 129
	private _extension: IExtension;
	get extension(): IExtension { return this._extension; }
	set extension(extension: IExtension) {
		this._extension = extension;
		this.installAction.extension = extension;
		this.uninstallAction.extension = extension;
	}
J
Joao Moreno 已提交
130

131 132 133
	constructor(
		@IInstantiationService instantiationService: IInstantiationService
	) {
J
Joao Moreno 已提交
134 135
		super('extensions.combinedInstall', '', '', false);

J
Joao Moreno 已提交
136 137
		this.installAction = instantiationService.createInstance(InstallAction);
		this.uninstallAction = instantiationService.createInstance(UninstallAction);
J
Joao Moreno 已提交
138 139
		this.disposables.push(this.installAction, this.uninstallAction);

140
		this.installAction.onDidChange(this.update, this, this.disposables);
141
		this.uninstallAction.onDidChange(this.update, this, this.disposables);
J
Joao Moreno 已提交
142 143 144 145
		this.update();
	}

	private update(): void {
J
Joao Moreno 已提交
146 147 148 149
		if (!this.extension) {
			this.enabled = false;
			this.class = CombinedInstallAction.NoExtensionClass;
		} else if (this.installAction.enabled) {
J
Joao Moreno 已提交
150 151 152 153 154 155 156
			this.enabled = true;
			this.label = this.installAction.label;
			this.class = this.installAction.class;
		} else if (this.uninstallAction.enabled) {
			this.enabled = true;
			this.label = this.uninstallAction.label;
			this.class = this.uninstallAction.class;
J
Joao Moreno 已提交
157 158 159 160
		} else if (this.extension.state === ExtensionState.Installing) {
			this.enabled = false;
			this.label = this.installAction.label;
			this.class = this.installAction.class;
J
Joao Moreno 已提交
161 162
		} else {
			this.enabled = false;
J
Joao Moreno 已提交
163 164
			this.label = this.installAction.label;
			this.class = this.installAction.class;
J
Joao Moreno 已提交
165 166 167 168 169 170 171 172 173 174 175 176 177
		}
	}

	run(): TPromise<any> {
		if (this.installAction.enabled) {
			return this.installAction.run();
		} else if (this.uninstallAction.enabled) {
			return this.uninstallAction.run();
		}

		return TPromise.as(null);
	}

J
Joao Moreno 已提交
178 179 180 181 182 183 184 185
	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
	}
}

export class UpdateAction extends Action {

J
Joao Moreno 已提交
186
	private static EnabledClass = 'extension-action update';
J
Joao Moreno 已提交
187 188 189
	private static DisabledClass = `${ UpdateAction.EnabledClass } disabled`;

	private disposables: IDisposable[] = [];
J
Joao Moreno 已提交
190 191 192
	private _extension: IExtension;
	get extension(): IExtension { return this._extension; }
	set extension(extension: IExtension) { this._extension = extension; this.update(); }
J
Joao Moreno 已提交
193

194 195 196
	constructor(
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
	) {
J
Joao Moreno 已提交
197
		super('extensions.update', localize('updateAction', "Update"), UpdateAction.DisabledClass, false);
J
Joao Moreno 已提交
198

J
Joao Moreno 已提交
199 200
		this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
		this.update();
J
Joao Moreno 已提交
201 202
	}

J
Joao Moreno 已提交
203 204 205 206 207 208 209
	private update(): void {
		if (!this.extension) {
			this.enabled = false;
			this.class = UpdateAction.DisabledClass;
			return;
		}

210
		const canInstall = this.extensionsWorkbenchService.canInstall(this.extension);
J
Joao Moreno 已提交
211 212
		const isInstalled = this.extension.state === ExtensionState.Installed
			|| this.extension.state === ExtensionState.NeedsRestart;
J
Joao Moreno 已提交
213

J
Joao Moreno 已提交
214
		this.enabled = canInstall && isInstalled && this.extension.outdated;
J
Joao Moreno 已提交
215 216 217 218
		this.class = this.enabled ? UpdateAction.EnabledClass : UpdateAction.DisabledClass;
	}

	run(): TPromise<any> {
219
		return this.extensionsWorkbenchService.install(this.extension);
J
Joao Moreno 已提交
220 221
	}

J
Joao Moreno 已提交
222 223 224 225 226 227 228 229 230 231 232 233
	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
	}
}

export class EnableAction extends Action {

	private static EnabledClass = 'extension-action enable';
	private static DisabledClass = `${ EnableAction.EnabledClass } disabled`;

	private disposables: IDisposable[] = [];
J
Joao Moreno 已提交
234 235 236
	private _extension: IExtension;
	get extension(): IExtension { return this._extension; }
	set extension(extension: IExtension) { this._extension = extension; this.update(); }
J
Joao Moreno 已提交
237 238 239 240 241 242 243

	constructor(
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
		@IInstantiationService private instantiationService: IInstantiationService
	) {
		super('extensions.enable', localize('enableAction', "Enable"), EnableAction.DisabledClass, false);

J
Joao Moreno 已提交
244 245
		this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
		this.update();
J
Joao Moreno 已提交
246 247
	}

J
Joao Moreno 已提交
248 249 250 251 252 253 254
	private update(): void {
		if (!this.extension) {
			this.enabled = false;
			this.class = EnableAction.DisabledClass;
			return;
		}

J
Joao Moreno 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267
		this.enabled = this.extension.state === ExtensionState.NeedsRestart;
		this.class = this.enabled ? EnableAction.EnabledClass : EnableAction.DisabledClass;
	}

	run(): TPromise<any> {
		if (!window.confirm(localize('restart', "In order to enable this extension, this window of VS Code needs to be restarted.\n\nDo you want to continue?"))) {
			return TPromise.as(null);
		}

		const action = this.instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, localize('restartNow', "Restart Now"));
		return action.run();
	}

J
Joao Moreno 已提交
268 269 270 271
	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
	}
272
}
J
Joao Moreno 已提交
273 274 275

export class UpdateAllAction extends Action {

276 277 278
	static ID = 'extensions.update-all';
	static LABEL = localize('updateAll', "Update All Extensions");

J
Joao Moreno 已提交
279 280 281
	private disposables: IDisposable[] = [];

	constructor(
282 283
		id = UpdateAllAction.ID,
		label = UpdateAllAction.LABEL,
J
Joao Moreno 已提交
284 285
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
	) {
286
		super(id, label, '', false);
J
Joao Moreno 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

		this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
		this.update();
	}

	private get outdated(): IExtension[] {
		return this.extensionsWorkbenchService.local
			.filter(e => this.extensionsWorkbenchService.canInstall(e)
				&& (e.state === ExtensionState.Installed || e.state === ExtensionState.NeedsRestart)
				&& e.outdated);
	}

	private update(): void {
		this.enabled = this.outdated.length > 0;
	}

	run(): TPromise<any> {
		return TPromise.join(this.outdated.map(e => this.extensionsWorkbenchService.install(e)));
	}

	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
	}
}
312 313 314

export class OpenExtensionsViewletAction extends ToggleViewletAction {

J
Joao Moreno 已提交
315
	static ID = VIEWLET_ID;
316 317 318 319 320 321 322 323 324 325 326 327
	static LABEL = localize('toggleExtensionsViewlet', "Show Extensions");

	constructor(
		id: string,
		label: string,
		@IViewletService viewletService: IViewletService,
		@IWorkbenchEditorService editorService: IWorkbenchEditorService
	) {
		super(id, label, VIEWLET_ID, viewletService, editorService);
	}
}

I
isidor 已提交
328 329 330 331 332
export class InstallExtensionsAction extends OpenExtensionsViewletAction {
	static ID = 'workbench.extensions.action.installExtensions';
	static LABEL = localize('installExtensions', "Install Extensions");
}

J
Joao Moreno 已提交
333
export class ShowInstalledExtensionsAction extends Action {
334

J
Joao Moreno 已提交
335 336
	static ID = 'workbench.extensions.action.showInstalledExtensions';
	static LABEL = localize('showInstalledExtensions', "Show Installed Extensions");
337 338 339 340

	constructor(
		id: string,
		label: string,
341 342
		@IViewletService private viewletService: IViewletService,
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
343
	) {
344
		super(id, label, 'clear-extensions', true);
345 346 347 348 349 350
	}

	run(): TPromise<void> {
		return this.viewletService.openViewlet(VIEWLET_ID, true)
			.then(viewlet => viewlet as IExtensionsViewlet)
			.then(viewlet => {
351
				viewlet.search('');
352 353 354 355 356
				viewlet.focus();
			});
	}
}

J
Joao Moreno 已提交
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
export class ClearExtensionsInputAction extends ShowInstalledExtensionsAction {

	static ID = 'workbench.extensions.action.clearExtensionsInput';
	static LABEL = localize('clearExtensionsInput', "Clear Extensions Input");

	private disposables: IDisposable[] = [];

	constructor(
		id: string,
		label: string,
		onSearchChange: Event<string>,
		@IViewletService viewletService: IViewletService,
		@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService
	) {
		super(id, label, viewletService, extensionsWorkbenchService);
372
		this.enabled = false;
J
Joao Moreno 已提交
373 374 375 376 377 378 379 380 381 382 383 384
		onSearchChange(this.onSearchChange, this, this.disposables);
	}

	private onSearchChange(value: string): void {
		this.enabled = !!value;
	}

	dispose(): void {
		this.disposables = dispose(this.disposables);
	}
}

J
Joao Moreno 已提交
385
export class ShowOutdatedExtensionsAction extends Action {
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402

	static ID = 'workbench.extensions.action.listOutdatedExtensions';
	static LABEL = localize('showOutdatedExtensions', "Show Outdated Extensions");

	constructor(
		id: string,
		label: string,
		@IViewletService private viewletService: IViewletService
	) {
		super(id, label, null, true);
	}

	run(): TPromise<void> {

		return this.viewletService.openViewlet(VIEWLET_ID, true)
			.then(viewlet => viewlet as IExtensionsViewlet)
			.then(viewlet => {
403
				viewlet.search('@outdated');
404 405 406 407 408 409 410 411
				viewlet.focus();
			});
	}

	protected isEnabled(): boolean {
		return true;
	}
}
J
Joao Moreno 已提交
412 413 414 415 416 417 418 419 420 421 422

export class ShowPopularExtensionsAction extends Action {

	static ID = 'workbench.extensions.action.showPopularExtensions';
	static LABEL = localize('showPopularExtensions', "Show Popular Extensions");

	constructor(
		id: string,
		label: string,
		@IViewletService private viewletService: IViewletService
	) {
423
		super(id, label, null, true);
J
Joao Moreno 已提交
424 425 426 427 428 429
	}

	run(): TPromise<void> {
		return this.viewletService.openViewlet(VIEWLET_ID, true)
			.then(viewlet => viewlet as IExtensionsViewlet)
			.then(viewlet => {
430
				viewlet.search('@sort:installs');
J
Joao Moreno 已提交
431 432 433 434 435 436 437 438 439
				viewlet.focus();
			});
	}

	protected isEnabled(): boolean {
		return true;
	}
}

J
Joao Moreno 已提交
440
export class ShowRecommendedExtensionsAction extends Action {
J
Joao Moreno 已提交
441

J
Joao Moreno 已提交
442
	static ID = 'workbench.extensions.action.showRecommendedExtensions';
J
Joao Moreno 已提交
443
	static LABEL = localize('showRecommendedExtensions', "Show Recommended Extensions");
J
Joao Moreno 已提交
444 445 446 447 448 449

	constructor(
		id: string,
		label: string,
		@IViewletService private viewletService: IViewletService
	) {
450
		super(id, label, null, true);
J
Joao Moreno 已提交
451 452 453 454 455 456
	}

	run(): TPromise<void> {
		return this.viewletService.openViewlet(VIEWLET_ID, true)
			.then(viewlet => viewlet as IExtensionsViewlet)
			.then(viewlet => {
457
				viewlet.search('@recommended');
J
Joao Moreno 已提交
458 459 460 461
				viewlet.focus();
			});
	}

J
Joao Moreno 已提交
462 463 464 465 466
	protected isEnabled(): boolean {
		return true;
	}
}

S
Sandeep Somavarapu 已提交
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493
export class ShowWorkspaceRecommendedExtensionsAction extends Action {

	static ID = 'workbench.extensions.action.showWorkspaceRecommendedExtensions';
	static LABEL = localize('showWorkspaceRecommendedExtensions', "Show Workspace Recommended Extensions");

	constructor(
		id: string,
		label: string,
		@IViewletService private viewletService: IViewletService
	) {
		super(id, label, null, true);
	}

	run(): TPromise<void> {
		return this.viewletService.openViewlet(VIEWLET_ID, true)
			.then(viewlet => viewlet as IExtensionsViewlet)
			.then(viewlet => {
				viewlet.search('@recommended:workspace');
				viewlet.focus();
			});
	}

	protected isEnabled(): boolean {
		return true;
	}
}

J
Joao Moreno 已提交
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
export class ChangeSortAction extends Action {

	private query: Query;
	private disposables: IDisposable[] = [];

	constructor(
		id: string,
		label: string,
		onSearchChange: Event<string>,
		private sortBy: string,
		private sortOrder: string,
		@IViewletService private viewletService: IViewletService
	) {
		super(id, label, null, true);

J
Joao Moreno 已提交
509
		if (sortBy === undefined && sortOrder === undefined) {
J
Joao Moreno 已提交
510 511 512 513
			throw new Error('bad arguments');
		}

		this.query = Query.parse('');
514
		this.enabled = false;
J
Joao Moreno 已提交
515 516 517 518 519 520
		onSearchChange(this.onSearchChange, this, this.disposables);
	}

	private onSearchChange(value: string): void {
		const query = Query.parse(value);
		this.query = new Query(query.value, this.sortBy || query.sortBy, this.sortOrder || query.sortOrder);
521
		this.enabled = value && this.query.isValid() && !this.query.equals(query);
J
Joao Moreno 已提交
522 523 524 525 526 527 528 529 530 531 532
	}

	run(): TPromise<void> {
		return this.viewletService.openViewlet(VIEWLET_ID, true)
			.then(viewlet => viewlet as IExtensionsViewlet)
			.then(viewlet => {
				viewlet.search(this.query.toString());
				viewlet.focus();
			});
	}

533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
	protected isEnabled(): boolean {
		return true;
	}
}

export class OpenExtensionsFolderAction extends Action {

	static ID = 'workbench.extensions.action.openExtensionsFolder';
	static LABEL = localize('openExtensionsFolder', "Open Extensions Folder");

	constructor(
		id: string,
		label: string,
		@IEnvironmentService private environmentService: IEnvironmentService
	) {
		super(id, label, null, true);
	}

	run(): TPromise<any> {
		const extensionsHome = this.environmentService.extensionsPath;
		shell.showItemInFolder(paths.normalize(extensionsHome, true));

		return TPromise.as(true);
	}

J
Joao Moreno 已提交
558 559 560
	protected isEnabled(): boolean {
		return true;
	}
S
Sandeep Somavarapu 已提交
561 562
}

S
Sandeep Somavarapu 已提交
563
export class ConfigureWorkspaceRecommendedExtensionsAction extends Action {
J
Joao Moreno 已提交
564

S
Sandeep Somavarapu 已提交
565 566
	static ID = 'workbench.extensions.action.configureWorkspaceRecommendedExtensions';
	static LABEL = localize('configureWorkspaceRecommendedExtensions', "Configure Workspace Recommended Extensions");
S
Sandeep Somavarapu 已提交
567

J
Joao Moreno 已提交
568 569 570 571 572 573 574 575 576
	constructor(
		id: string,
		label: string,
		@IFileService private fileService: IFileService,
		@IWorkspaceContextService private contextService: IWorkspaceContextService,
		@IExtensionsWorkbenchService private extensionsService: IExtensionsWorkbenchService,
		@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
		@IMessageService private messageService: IMessageService
	) {
S
Sandeep Somavarapu 已提交
577 578 579 580
		super(id, label, null, true);
	}

	public run(event: any): TPromise<any> {
J
Joao Moreno 已提交
581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
		return this.openExtensionsFile();
	}

	private openExtensionsFile(): TPromise<any> {
		if (!this.contextService.getWorkspace()) {
			this.messageService.show(severity.Info, localize('ConfigureWorkspaceRecommendations.noWorkspace', 'Recommendations are only available on a workspace folder.'));
			return TPromise.as(undefined);
		}

		return this.getOrCreateExtensionsFile().then(value => {
			return this.editorService.openEditor({
				resource: value.extensionsFileResource,
				options: {
					forceOpen: true,
					pinned: value.created
				},
			});
		}, (error) => TPromise.wrapError(new Error(localize('OpenExtensionsFile.failed', "Unable to create 'extensions.json' file inside the '.vscode' folder ({0}).", error))));
	}

	private getOrCreateExtensionsFile(): TPromise<{ created: boolean, extensionsFileResource: URI }> {
		const extensionsFileResource = URI.file(paths.join(this.contextService.getWorkspace().resource.fsPath, '.vscode', `${ ConfigurationKey }.json`));

		return this.fileService.resolveContent(extensionsFileResource).then(content => {
			return { created: false, extensionsFileResource };
		}, err => {
			return this.fileService.updateContent(extensionsFileResource, InitialContent).then(() => {
				return { created: true, extensionsFileResource };
			});
		});
S
Sandeep Somavarapu 已提交
611
	}
J
Joao Moreno 已提交
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
}

export class InstallVSIXAction extends Action {

	static ID = 'workbench.extensions.action.installVSIX';
	static LABEL = localize('installVSIX', "Install from VSIX...");

	constructor(
		id = InstallVSIXAction.ID,
		label = InstallVSIXAction.LABEL,
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
	) {
		super(id, label, 'extension-action install-vsix', true);
	}

	run(): TPromise<any> {
		const result = dialog.showOpenDialog(remote.getCurrentWindow(), {
			filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],
			properties: ['openFile']
		});

		if (!result) {
			return TPromise.as(null);
		}

		return TPromise.join(result.map(vsix => this.extensionsWorkbenchService.install(vsix)));
	}
639
}