extensionsActions.ts 15.8 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';
J
Joao Moreno 已提交
10 11 12 13 14
// import { assign } from 'vs/base/common/objects';
// import Severity from 'vs/base/common/severity';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
// import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
// import { IMessageService } from 'vs/platform/message/common/message';
J
Joao Moreno 已提交
15
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
16
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet } from './extensions';
17
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
J
Joao Moreno 已提交
18 19
// import { extensionEquals, getTelemetryData } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
// import { IQuickOpenService } from 'vs/workbench/services/quickopen/common/quickOpenService';
20 21 22
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 已提交
23

J
Joao Moreno 已提交
24
// const CloseAction = new Action('action.close', localize('close', "Close"));
J
Joao Moreno 已提交
25 26 27 28

// export class ListExtensionsAction extends Action {

// 	static ID = 'workbench.extensions.action.listExtensions';
J
Joao Moreno 已提交
29
// 	static LABEL = localize('showInstalledExtensions', "Show Installed Extensions");
J
Joao Moreno 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

// 	constructor(
// 		id: string,
// 		label: string,
// 		@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
// 		@IQuickOpenService private quickOpenService: IQuickOpenService
// 	) {
// 		super(id, label, null, true);
// 	}

// 	run(): Promise {
// 		return this.quickOpenService.show('ext ');
// 	}

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

// export class InstallExtensionAction extends Action {

// 	static ID = 'workbench.extensions.action.installExtension';
J
Joao Moreno 已提交
52
// 	static LABEL = localize('installExtension', "Install Extension");
J
Joao Moreno 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

// 	constructor(
// 		id: string,
// 		label: string,
// 		@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
// 		@IQuickOpenService private quickOpenService: IQuickOpenService
// 	) {
// 		super(id, label, null, true);
// 	}

// 	run(): Promise {
// 		return this.quickOpenService.show('ext install ');
// 	}

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

// export class ListOutdatedExtensionsAction extends Action {

// 	static ID = 'workbench.extensions.action.listOutdatedExtensions';
J
Joao Moreno 已提交
75
// 	static LABEL = localize('showOutdatedExtensions', "Show Outdated Extensions");
J
Joao Moreno 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

// 	constructor(
// 		id: string,
// 		label: string,
// 		@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
// 		@IQuickOpenService private quickOpenService: IQuickOpenService
// 	) {
// 		super(id, label, null, true);
// 	}

// 	run(): Promise {
// 		return this.quickOpenService.show('ext update ');
// 	}

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

// export class ListSuggestedExtensionsAction extends Action {

// 	static ID = 'workbench.extensions.action.listSuggestedExtensions';
J
Joao Moreno 已提交
98
// 	static LABEL = localize('showExtensionRecommendations', "Show Extension Recommendations");
J
Joao Moreno 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

// 	constructor(
// 		id: string,
// 		label: string,
// 		@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
// 		@IQuickOpenService private quickOpenService: IQuickOpenService
// 	) {
// 		super(id, label, null, true);
// 	}

// 	run(): Promise {
// 		return this.quickOpenService.show('ext recommend ');
// 	}

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

118 119
export class InstallAction extends Action {

J
Joao Moreno 已提交
120 121
	private static InstallLabel = localize('installAction', "Install");
	private static InstallingLabel = localize('installing', "Installing");
J
Joao Moreno 已提交
122
	private disposables: IDisposable[] = [];
123

124 125 126 127
	constructor(
		private extension: IExtension,
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
	) {
J
Joao Moreno 已提交
128
		super('extensions.install', InstallAction.InstallLabel, 'extension-action install', false);
129

130
		this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
J
Joao Moreno 已提交
131
		this.update();
132 133
	}

J
Joao Moreno 已提交
134
	private update(): void {
135
		this.enabled = this.extensionsWorkbenchService.canInstall(this.extension) && this.extension.state === ExtensionState.Uninstalled;
J
Joao Moreno 已提交
136
		this.label = this.extension.state === ExtensionState.Installing ? InstallAction.InstallingLabel : InstallAction.InstallLabel;
137 138
	}

J
Joao Moreno 已提交
139
	run(): TPromise<any> {
140
		return this.extensionsWorkbenchService.install(this.extension);
J
Joao Moreno 已提交
141

J
Joao Moreno 已提交
142
		// this.enabled = false;
143

J
Joao Moreno 已提交
144 145 146 147 148 149 150 151 152
		// return this.extensionManagementService.getInstalled()
		// 	.then(installed => installed.some(({ manifest }) => extensionEquals(manifest, extension)))
		// 	.then(isUpdate => {
		// 		return this.extensionManagementService
		// 			.install(extension)
		// 			.then(() => this.onSuccess(extension, isUpdate), err => this.onError(err, extension, isUpdate))
		// 			.then(() => this.enabled = true)
		// 			.then(() => null);
		// 	});
153 154
	}

J
Joao Moreno 已提交
155 156 157
	// private onSuccess(extension: IGalleryExtension, isUpdate: boolean) {
	// 	this.reportTelemetry(extension, isUpdate, true);
	// 	this.messageService.show(Severity.Info, {
J
Joao Moreno 已提交
158
	// 		message: localize('success-installed', "'{0}' was successfully installed. Restart to enable it.", extension.displayName || extension.name),
J
Joao Moreno 已提交
159 160
	// 		actions: [
	// 			CloseAction,
J
Joao Moreno 已提交
161
	// 			this.instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, localize('restartNow', "Restart Now"))
J
Joao Moreno 已提交
162 163 164
	// 		]
	// 	});
	// }
165

J
Joao Moreno 已提交
166 167 168 169
	// private onError(err: Error, extension: IGalleryExtension, isUpdate: boolean) {
	// 	this.reportTelemetry(extension, isUpdate, false);
	// 	this.messageService.show(Severity.Error, err);
	// }
170

J
Joao Moreno 已提交
171 172 173
	// private reportTelemetry(extension: IGalleryExtension, isUpdate: boolean, success: boolean) {
	// 	const event = isUpdate ? 'extensionGallery:update' : 'extensionGallery:install';
	// 	const data = assign(getTelemetryData(extension), { success });
174

J
Joao Moreno 已提交
175 176
	// 	this.telemetryService.publicLog(event, data);
	// }
J
Joao Moreno 已提交
177

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

J
Joao Moreno 已提交
184
export class UninstallAction extends Action {
J
Joao Moreno 已提交
185

J
Joao Moreno 已提交
186
	private disposables: IDisposable[] = [];
J
Joao Moreno 已提交
187

188 189 190 191
	constructor(
		private extension: IExtension,
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
	) {
J
Joao Moreno 已提交
192
		super('extensions.uninstall', localize('uninstall', "Uninstall"), 'extension-action uninstall', false);
J
Joao Moreno 已提交
193

194
		this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.updateEnablement()));
J
Joao Moreno 已提交
195 196
		this.updateEnablement();
	}
J
Joao Moreno 已提交
197

J
Joao Moreno 已提交
198
	private updateEnablement(): void {
J
Joao Moreno 已提交
199 200
		this.enabled = this.extension.state === ExtensionState.Installed
			|| this.extension.state === ExtensionState.NeedsRestart;
J
Joao Moreno 已提交
201
	}
J
Joao Moreno 已提交
202

J
Joao Moreno 已提交
203 204
	run(): TPromise<any> {
		// const name = extension.manifest.displayName || extension.manifest.name;
J
Joao Moreno 已提交
205

J
Joao Moreno 已提交
206
		if (!window.confirm(localize('deleteSure', "Are you sure you want to uninstall '{0}'?", this.extension.displayName))) {
J
Joao Moreno 已提交
207 208
			return TPromise.as(null);
		}
J
Joao Moreno 已提交
209

210
		return this.extensionsWorkbenchService.uninstall(this.extension);
J
Joao Moreno 已提交
211 212 213 214 215 216 217

		// this.enabled = false;

		// return this.extensionManagementService.getInstalled().then(localExtensions => {
		// 	const [local] = localExtensions.filter(local => extensionEquals(local.manifest, extension.manifest));

		// 	if (!local) {
J
Joao Moreno 已提交
218
		// 		return TPromise.wrapError(localize('notFound', "Extension '{0}' not installed.", name));
J
Joao Moreno 已提交
219 220 221 222 223 224 225 226
		// 	}

		// 	return this.extensionManagementService.uninstall(local)
		// 		.then(() => this.onSuccess(local), err => this.onError(err, local))
		// 		.then(() => this.enabled = true)
		// 		.then(() => null);
		// });
	}
J
Joao Moreno 已提交
227 228 229 230 231 232

// 	private onSuccess(extension: ILocalExtension) {
// 		const name = extension.manifest.displayName || extension.manifest.name;
// 		this.reportTelemetry(extension, true);

// 		this.messageService.show(Severity.Info, {
J
Joao Moreno 已提交
233
// 			message: localize('success-uninstalled', "'{0}' was successfully uninstalled. Restart to deactivate it.", name),
J
Joao Moreno 已提交
234 235
// 			actions: [
// 				CloseAction,
J
Joao Moreno 已提交
236
// 				this.instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, localize('restartNow2', "Restart Now"))
J
Joao Moreno 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250
// 			]
// 		});
// 	}

// 	private onError(err: Error, extension: ILocalExtension) {
// 		this.reportTelemetry(extension, false);
// 		this.messageService.show(Severity.Error, err);
// 	}

// 	private reportTelemetry(extension: ILocalExtension, success: boolean) {
// 		const data = assign(getTelemetryData(extension), { success });

// 		this.telemetryService.publicLog('extensionGallery:uninstall', data);
// 	}
J
Joao Moreno 已提交
251 252 253 254 255 256

	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
	}
}
J
Joao Moreno 已提交
257 258 259 260 261 262 263

export class CombinedInstallAction extends Action {

	private installAction: InstallAction;
	private uninstallAction: UninstallAction;
	private disposables: IDisposable[] = [];

264 265 266 267
	constructor(
		private extension: IExtension,
		@IInstantiationService instantiationService: IInstantiationService
	) {
J
Joao Moreno 已提交
268 269
		super('extensions.combinedInstall', '', '', false);

270 271
		this.installAction = instantiationService.createInstance(InstallAction, extension);
		this.uninstallAction = instantiationService.createInstance(UninstallAction, extension);
J
Joao Moreno 已提交
272 273 274
		this.disposables.push(this.installAction, this.uninstallAction);

		this.disposables.push(this.installAction.addListener2(Action.ENABLED, () => this.update()));
J
Joao Moreno 已提交
275
		this.disposables.push(this.installAction.addListener2(Action.LABEL, () => this.update()));
J
Joao Moreno 已提交
276 277 278 279 280 281 282 283 284 285 286 287 288
		this.disposables.push(this.uninstallAction.addListener2(Action.ENABLED, () => this.update()));
		this.update();
	}

	private update(): void {
		if (this.installAction.enabled) {
			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 已提交
289 290 291 292
		} else if (this.extension.state === ExtensionState.Installing) {
			this.enabled = false;
			this.label = this.installAction.label;
			this.class = this.installAction.class;
J
Joao Moreno 已提交
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
		} else {
			this.enabled = false;
		}
	}

	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 已提交
308 309 310 311 312 313 314 315
	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
	}
}

export class UpdateAction extends Action {

J
Joao Moreno 已提交
316
	private static EnabledClass = 'extension-action update';
J
Joao Moreno 已提交
317 318 319 320
	private static DisabledClass = `${ UpdateAction.EnabledClass } disabled`;

	private disposables: IDisposable[] = [];

321 322 323 324
	constructor(
		private extension: IExtension,
		@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
	) {
J
Joao Moreno 已提交
325
		super('extensions.update', localize('updateAction', "Update"), UpdateAction.DisabledClass, false);
J
Joao Moreno 已提交
326

327
		this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.updateEnablement()));
J
Joao Moreno 已提交
328 329 330 331
		this.updateEnablement();
	}

	private updateEnablement(): void {
332
		const canInstall = this.extensionsWorkbenchService.canInstall(this.extension);
J
Joao Moreno 已提交
333 334
		const isInstalled = this.extension.state === ExtensionState.Installed
			|| this.extension.state === ExtensionState.NeedsRestart;
J
Joao Moreno 已提交
335

J
Joao Moreno 已提交
336
		this.enabled = canInstall && isInstalled && this.extension.outdated;
J
Joao Moreno 已提交
337 338 339 340
		this.class = this.enabled ? UpdateAction.EnabledClass : UpdateAction.DisabledClass;
	}

	run(): TPromise<any> {
341
		return this.extensionsWorkbenchService.install(this.extension);
J
Joao Moreno 已提交
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358

		// this.enabled = false;

		// return this.extensionManagementService.getInstalled()
		// 	.then(installed => installed.some(({ manifest }) => extensionEquals(manifest, extension)))
		// 	.then(isUpdate => {
		// 		return this.extensionManagementService
		// 			.install(extension)
		// 			.then(() => this.onSuccess(extension, isUpdate), err => this.onError(err, extension, isUpdate))
		// 			.then(() => this.enabled = true)
		// 			.then(() => null);
		// 	});
	}

	// private onSuccess(extension: IGalleryExtension, isUpdate: boolean) {
	// 	this.reportTelemetry(extension, isUpdate, true);
	// 	this.messageService.show(Severity.Info, {
J
Joao Moreno 已提交
359
	// 		message: localize('success-installed', "'{0}' was successfully installed. Restart to enable it.", extension.displayName || extension.name),
J
Joao Moreno 已提交
360 361
	// 		actions: [
	// 			CloseAction,
J
Joao Moreno 已提交
362
	// 			this.instantiationService.createInstance(ReloadWindowAction, ReloadWindowAction.ID, localize('restartNow', "Restart Now"))
J
Joao Moreno 已提交
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
	// 		]
	// 	});
	// }

	// private onError(err: Error, extension: IGalleryExtension, isUpdate: boolean) {
	// 	this.reportTelemetry(extension, isUpdate, false);
	// 	this.messageService.show(Severity.Error, err);
	// }

	// private reportTelemetry(extension: IGalleryExtension, isUpdate: boolean, success: boolean) {
	// 	const event = isUpdate ? 'extensionGallery:update' : 'extensionGallery:install';
	// 	const data = assign(getTelemetryData(extension), { success });

	// 	this.telemetryService.publicLog(event, data);
	// }

J
Joao Moreno 已提交
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
	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[] = [];

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

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

	private updateEnablement(): void {
		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 已提交
417 418 419 420
	dispose(): void {
		super.dispose();
		this.disposables = dispose(this.disposables);
	}
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
}

export class OpenExtensionsViewletAction extends ToggleViewletAction {

	static ID = 'workbench.extensions.showViewlet';
	static LABEL = localize('toggleExtensionsViewlet', "Show Extensions");

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

export class ListOutdatedExtensionsAction extends Action {

	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 => {
				viewlet.search('@outdated', true);
				viewlet.focus();
			});
	}

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