extensionsModel.ts 5.9 KB
Newer Older
J
Joao Moreno 已提交
1 2 3 4 5 6 7 8 9
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

'use strict';

import 'vs/css!./media/extensionsViewlet';
import Event, { Emitter } from 'vs/base/common/event';
10
import { index } from 'vs/base/common/arrays';
J
Joao Moreno 已提交
11 12
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
J
Joao Moreno 已提交
13
import { IPager, mapPager } from 'vs/base/common/paging';
J
Joao Moreno 已提交
14 15 16 17 18
import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions } from 'vs/platform/extensionManagement/common/extensionManagement';

export enum ExtensionState {
	Installing,
	Installed,
J
Joao Moreno 已提交
19
	// Uninstalling,
J
Joao Moreno 已提交
20 21 22 23
	Uninstalled
}

export interface IExtension {
J
Joao Moreno 已提交
24
	state: ExtensionState;
J
Joao Moreno 已提交
25 26
	name: string;
	displayName: string;
J
Joao Moreno 已提交
27 28
	publisher: string;
	publisherDisplayName: string;
J
Joao Moreno 已提交
29 30 31 32 33
	version: string;
	description: string;
	iconUrl: string;
}

J
Joao Moreno 已提交
34 35 36 37
interface IExtensionStateProvider {
	(extension: Extension): ExtensionState;
}

J
Joao Moreno 已提交
38 39
class Extension implements IExtension {

J
Joao Moreno 已提交
40
	constructor(
J
Joao Moreno 已提交
41
		private stateProvider: IExtensionStateProvider,
J
Joao Moreno 已提交
42 43
		public local: ILocalExtension,
		public gallery: IGalleryExtension = null
J
Joao Moreno 已提交
44
	) {}
J
Joao Moreno 已提交
45 46 47 48 49

	get name(): string {
		return this.local ? this.local.manifest.name : this.gallery.name;
	}

J
Joao Moreno 已提交
50 51 52 53 54 55 56 57
	get displayName(): string {
		if (this.local) {
			return this.local.manifest.displayName || this.local.manifest.name;
		}

		return this.gallery.displayName || this.gallery.name;
	}

J
Joao Moreno 已提交
58
	get publisher(): string {
J
Joao Moreno 已提交
59 60 61 62
		return this.local ? this.local.manifest.publisher : this.gallery.publisher;
	}

	get publisherDisplayName(): string {
J
Joao Moreno 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
		if (this.local) {
			if (this.local.metadata && this.local.metadata.publisherDisplayName) {
				return this.local.metadata.publisherDisplayName;
			}

			return this.local.manifest.publisher;
		}

		return this.gallery.publisherDisplayName || this.gallery.publisher;
	}

	get version(): string {
		return this.local ? this.local.manifest.version : this.gallery.versions[0].version;
	}

	get description(): string {
		return this.local ? this.local.manifest.description : this.gallery.description;
	}

	get iconUrl(): string {
		if (this.local && this.local.manifest.icon) {
			return `file://${ this.local.path }/${ this.local.manifest.icon }`;
		}

		if (this.gallery && this.gallery.versions[0].iconUrl) {
			return this.gallery.versions[0].iconUrl;
		}

		return require.toUrl('./media/defaultIcon.png');
	}
J
Joao Moreno 已提交
93 94 95 96

	get state(): ExtensionState {
		return this.stateProvider(this);
	}
J
Joao Moreno 已提交
97 98 99 100 101 102
}

export class ExtensionsModel {

	private disposables: IDisposable[] = [];

J
Joao Moreno 已提交
103 104
	private stateProvider: IExtensionStateProvider;
	private installing: { id: string; extension: Extension; }[] = [];
105
	private installed: Extension[] = [];
J
Joao Moreno 已提交
106

J
Joao Moreno 已提交
107
	private _onChange: Emitter<void> = new Emitter<void>();
J
Joao Moreno 已提交
108 109 110 111 112 113
	get onChange(): Event<void> { return this._onChange.event; }

	constructor(
		@IExtensionManagementService private extensionService: IExtensionManagementService,
		@IExtensionGalleryService private galleryService: IExtensionGalleryService
	) {
J
Joao Moreno 已提交
114
		this.stateProvider = ext => this.getExtensionState(ext);
J
Joao Moreno 已提交
115 116
		this.disposables.push(extensionService.onInstallExtension(({ id, gallery }) => this.onInstallExtension(id, gallery)));
		this.disposables.push(extensionService.onDidInstallExtension(({ id, local, error }) => this.onDidInstallExtension(id, local, error)));
J
Joao Moreno 已提交
117 118
	}

J
Joao Moreno 已提交
119
	getLocal(): TPromise<IExtension[]> {
120 121 122 123 124
		return this.extensionService.getInstalled().then(result => {
			const installedById = index(this.installed, e => e.local.id);

			this.installed = result.map(local => {
				const id = local.path;
J
Joao Moreno 已提交
125
				const extension = installedById[id] || new Extension(this.stateProvider, local);
126 127 128 129 130 131
				extension.local = local;
				return extension;
			});

			return this.installed;
		});
J
Joao Moreno 已提交
132 133 134
	}

	queryGallery(options: IQueryOptions = {}): TPromise<IPager<IExtension>> {
135 136 137 138 139 140 141 142 143 144 145 146
		return this.galleryService.query(options).then(result => {
			const installedByGalleryId = index(this.installed, e => e.local.metadata ? e.local.metadata.id : '');

			return mapPager(result, gallery => {
				const id = gallery.id;
				const installed = installedByGalleryId[id];

				if (installed) {
					installed.gallery = gallery;
					return installed;
				}

J
Joao Moreno 已提交
147
				return new Extension(this.stateProvider, null, gallery);
148 149
			});
		});
J
Joao Moreno 已提交
150 151
	}

J
Joao Moreno 已提交
152
	install(extension: IExtension): TPromise<void> {
J
Joao Moreno 已提交
153 154 155 156 157
		if (!(extension instanceof Extension)) {
			return;
		}

		const ext = extension as Extension;
J
Joao Moreno 已提交
158
		const gallery = ext.gallery;
J
Joao Moreno 已提交
159

J
Joao Moreno 已提交
160 161
		if (!gallery) {
			return TPromise.wrapError<void>(new Error('Missing gallery'));
J
Joao Moreno 已提交
162 163
		}

J
Joao Moreno 已提交
164
		return this.extensionService.install(gallery);
J
Joao Moreno 已提交
165 166
	}

J
Joao Moreno 已提交
167 168 169 170 171 172 173 174
	private onInstallExtension(id: string, gallery: IGalleryExtension): void {
		if (!gallery) {
			return;
		}

		let extension = this.installed.filter(e => (e.local.metadata && e.local.metadata.id) === gallery.id)[0];

		if (!extension) {
J
Joao Moreno 已提交
175
			extension = new Extension(this.stateProvider, null, gallery);
J
Joao Moreno 已提交
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
		}

		extension.gallery = gallery;
		this.installing.push({ id, extension });

		this._onChange.fire();
	}

	private onDidInstallExtension(id: string, local: ILocalExtension, error: Error): void {
		const installing = this.installing.filter(e => e.id === id)[0];

		if (!installing) {
			return;
		}

		const extension = installing.extension;
		extension.local = local;

		this.installing = this.installing.filter(e => e.id !== id);
		this.installed.push(extension);

		this._onChange.fire();
	}

J
Joao Moreno 已提交
200 201 202 203 204 205 206 207 208 209 210 211
	private getExtensionState(extension: Extension): ExtensionState {
		if (this.installed.indexOf(extension) > -1) {
			return ExtensionState.Installed;
		}

		if (this.installing.some(e => e.extension === extension)) {
			return ExtensionState.Installing;
		}

		return ExtensionState.Uninstalled;
	}

J
Joao Moreno 已提交
212 213 214 215
	dispose(): void {
		this.disposables = dispose(this.disposables);
	}
}