提交 1edee67e 编写于 作者: J Joao Moreno

Merge branch 'install-count' of https://github.com/wadeanderson/vscode into...

Merge branch 'install-count' of https://github.com/wadeanderson/vscode into wadeanderson-install-count
...@@ -15,6 +15,7 @@ export interface IExtensionManifest { ...@@ -15,6 +15,7 @@ export interface IExtensionManifest {
version: string; version: string;
displayName?: string; displayName?: string;
description?: string; description?: string;
installs: number;
} }
export interface IGalleryInformation { export interface IGalleryInformation {
......
...@@ -56,7 +56,7 @@ interface ITemplateData { ...@@ -56,7 +56,7 @@ interface ITemplateData {
root: HTMLElement; root: HTMLElement;
displayName: HighlightedLabel; displayName: HighlightedLabel;
version: HTMLElement; version: HTMLElement;
since: HTMLElement; installs: HTMLElement;
author: HTMLElement; author: HTMLElement;
actionbar: ActionBar; actionbar: ActionBar;
description: HighlightedLabel; description: HighlightedLabel;
...@@ -79,10 +79,11 @@ function extensionEquals(one: IExtension, other: IExtension): boolean { ...@@ -79,10 +79,11 @@ function extensionEquals(one: IExtension, other: IExtension): boolean {
return one.publisher === other.publisher && one.name === other.name; return one.publisher === other.publisher && one.name === other.name;
} }
/**
* Compare by Install count descending.
*/
function extensionEntryCompare(one: IExtensionEntry, other: IExtensionEntry): number { function extensionEntryCompare(one: IExtensionEntry, other: IExtensionEntry): number {
const oneName = one.extension.displayName || one.extension.name; return other.extension.installs - one.extension.installs;
const otherName = other.extension.displayName || other.extension.name;
return oneName.localeCompare(otherName);
} }
class OpenInGalleryAction extends Action { class OpenInGalleryAction extends Action {
...@@ -171,19 +172,22 @@ class Renderer implements IRenderer<IExtensionEntry> { ...@@ -171,19 +172,22 @@ class Renderer implements IRenderer<IExtensionEntry> {
} }
renderTemplate(templateId: string, container: HTMLElement): ITemplateData { renderTemplate(templateId: string, container: HTMLElement): ITemplateData {
// Important to preserve order here.
const root = dom.append(container, $('.extension')); const root = dom.append(container, $('.extension'));
const firstRow = dom.append(root, $('.row')); const firstRow = dom.append(root, $('.row'));
const secondRow = dom.append(root, $('.row')); const secondRow = dom.append(root, $('.row'));
const published = dom.append(firstRow, $('.published')); const published = dom.append(firstRow, $('.published'));
const since = dom.append(published, $('span.since')); const displayName = new HighlightedLabel(dom.append(firstRow, $('span.name')));
const installs = dom.append(firstRow, $('span.installs'));
const version = dom.append(published, $('span.version'));
const author = dom.append(published, $('span.author')); const author = dom.append(published, $('span.author'));
return { return {
root, root,
author, author,
since, displayName,
displayName: new HighlightedLabel(dom.append(firstRow, $('span.name'))), version,
version: dom.append(firstRow, $('span.version')), installs,
actionbar: new ActionBar(dom.append(secondRow, $('.actions'))), actionbar: new ActionBar(dom.append(secondRow, $('.actions'))),
description: new HighlightedLabel(dom.append(secondRow, $('span.description'))), description: new HighlightedLabel(dom.append(secondRow, $('span.description'))),
disposables: [] disposables: []
...@@ -194,6 +198,7 @@ class Renderer implements IRenderer<IExtensionEntry> { ...@@ -194,6 +198,7 @@ class Renderer implements IRenderer<IExtensionEntry> {
const extension = entry.extension; const extension = entry.extension;
const date = extension.galleryInformation ? extension.galleryInformation.date : null; const date = extension.galleryInformation ? extension.galleryInformation.date : null;
const publisher = extension.galleryInformation ? extension.galleryInformation.publisherDisplayName : extension.publisher; const publisher = extension.galleryInformation ? extension.galleryInformation.publisherDisplayName : extension.publisher;
const installs = extension.installs;
const actionOptions = { icon: true, label: false }; const actionOptions = { icon: true, label: false };
const updateActions = () => { const updateActions = () => {
...@@ -236,7 +241,7 @@ class Renderer implements IRenderer<IExtensionEntry> { ...@@ -236,7 +241,7 @@ class Renderer implements IRenderer<IExtensionEntry> {
data.displayName.set(extension.displayName, entry.highlights.displayName); data.displayName.set(extension.displayName, entry.highlights.displayName);
data.displayName.element.title = extension.name; data.displayName.element.title = extension.name;
data.version.textContent = extension.version; data.version.textContent = extension.version;
data.since.textContent = date ? since(new Date(date)) : ''; data.installs.textContent = String(installs);
data.author.textContent = publisher; data.author.textContent = publisher;
data.description.set(extension.description, entry.highlights.description); data.description.set(extension.description, entry.highlights.description);
data.description.element.title = extension.description; data.description.element.title = extension.description;
......
...@@ -28,12 +28,12 @@ ...@@ -28,12 +28,12 @@
opacity: 0.6; opacity: 0.6;
} }
.quick-open-widget .extension .version { .quick-open-widget .extension .installs {
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback"; font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
font-size: smaller; font-size: smaller;
} }
.quick-open-widget .extension .version { .quick-open-widget .extension .installs {
padding-left: 6px; padding-left: 6px;
opacity: 0.7; opacity: 0.7;
} }
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
font-size: smaller; font-size: smaller;
} }
.quick-open-widget .extension .published > .since { .quick-open-widget .extension .published > .version {
opacity: 0.6; opacity: 0.6;
margin-right: 0.5em; margin-right: 0.5em;
} }
......
...@@ -64,7 +64,8 @@ function createExtension(manifest: IExtensionManifest, galleryInformation?: IGal ...@@ -64,7 +64,8 @@ function createExtension(manifest: IExtensionManifest, galleryInformation?: IGal
displayName: manifest.displayName || manifest.name, displayName: manifest.displayName || manifest.name,
publisher: manifest.publisher, publisher: manifest.publisher,
version: manifest.version, version: manifest.version,
description: manifest.description || '' description: manifest.description || '',
installs: 0
}; };
if (galleryInformation) { if (galleryInformation) {
......
...@@ -33,6 +33,12 @@ export interface IGalleryExtension { ...@@ -33,6 +33,12 @@ export interface IGalleryExtension {
publisher: { displayName: string, publisherId: string, publisherName: string; }; publisher: { displayName: string, publisherId: string, publisherName: string; };
versions: IGalleryExtensionVersion[]; versions: IGalleryExtensionVersion[];
galleryApiUrl: string; galleryApiUrl: string;
statistics: IGalleryExtensionStatistic[];
}
export interface IGalleryExtensionStatistic {
statisticName: string;
value: number;
} }
export class GalleryService implements IGalleryService { export class GalleryService implements IGalleryService {
...@@ -53,10 +59,32 @@ export class GalleryService implements IGalleryService { ...@@ -53,10 +59,32 @@ export class GalleryService implements IGalleryService {
return `${ this.extensionsGalleryUrl }${ path }`; return `${ this.extensionsGalleryUrl }${ path }`;
} }
/**
* Extracts install count statistic.
*/
private extractInstalls(statistics: IGalleryExtensionStatistic[]): number {
// Sometimes there are no statistics.
if (!statistics) {
return 0;
}
var result = 0;
statistics.forEach(stat => {
if (stat.statisticName === 'install') {
result = stat.value;
}
})
return result;
}
public isEnabled(): boolean { public isEnabled(): boolean {
return !!this.extensionsGalleryUrl; return !!this.extensionsGalleryUrl;
} }
/**
* Queries VS Code Extension marketplace for extensions.
*
* Sorts by install count.
*/
public query(): TPromise<IExtension[]> { public query(): TPromise<IExtension[]> {
if (!this.extensionsGalleryUrl) { if (!this.extensionsGalleryUrl) {
return TPromise.wrapError(new Error('No extension gallery service configured.')); return TPromise.wrapError(new Error('No extension gallery service configured.'));
...@@ -69,7 +97,7 @@ export class GalleryService implements IGalleryService { ...@@ -69,7 +97,7 @@ export class GalleryService implements IGalleryService {
value: 'vscode' value: 'vscode'
}] }]
}], }],
flags: 0x1 | 0x4 | 0x80 flags: 0x1 | 0x4 | 0x80 | 0x100
}); });
const request = { const request = {
...@@ -92,13 +120,14 @@ export class GalleryService implements IGalleryService { ...@@ -92,13 +120,14 @@ export class GalleryService implements IGalleryService {
publisher: extension.publisher.publisherName, publisher: extension.publisher.publisherName,
version: extension.versions[0].version, version: extension.versions[0].version,
description: extension.shortDescription || '', description: extension.shortDescription || '',
installs: this.extractInstalls(extension.statistics),
galleryInformation: { galleryInformation: {
galleryApiUrl: this.extensionsGalleryUrl, galleryApiUrl: this.extensionsGalleryUrl,
id: extension.extensionId, id: extension.extensionId,
downloadUrl: `${ extension.versions[0].assetUri }/Microsoft.VisualStudio.Services.VSIXPackage?install=true`, downloadUrl: `${ extension.versions[0].assetUri }/Microsoft.VisualStudio.Services.VSIXPackage?install=true`,
publisherId: extension.publisher.publisherId, publisherId: extension.publisher.publisherId,
publisherDisplayName: extension.publisher.displayName, publisherDisplayName: extension.publisher.displayName,
date: extension.versions[0].lastUpdated date: extension.versions[0].lastUpdated,
} }
})); }));
}); });
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册