提交 862ac8d8 编写于 作者: J Joao Moreno

extensions: built-in

上级 fc7de67c
......@@ -19,7 +19,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import { IEventService } from 'vs/platform/event/common/event';
import { EventService } from 'vs/platform/event/common/eventService';
import { IExtensionManagementService, IExtensionGalleryService, IExtensionManifest, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementService, IExtensionGalleryService, IExtensionManifest, IGalleryExtension, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { ITelemetryService, combinedAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetry';
......@@ -66,7 +66,7 @@ class Main {
}
private listExtensions(): TPromise<any> {
return this.extensionManagementService.getInstalled().then(extensions => {
return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(extensions => {
extensions.forEach(e => console.log(getId(e.manifest)));
});
}
......@@ -85,7 +85,7 @@ class Main {
const galleryTasks: Task[] = extensions
.filter(e => !/\.vsix$/i.test(e))
.map(id => () => {
return this.extensionManagementService.getInstalled().then(installed => {
return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(installed => {
const isInstalled = installed.some(e => getId(e.manifest) === id);
if (isInstalled) {
......@@ -127,7 +127,7 @@ class Main {
private uninstallExtension(ids: string[]): TPromise<any> {
return sequence(ids.map(id => () => {
return this.extensionManagementService.getInstalled().then(installed => {
return this.extensionManagementService.getInstalled(LocalExtensionType.User).then(installed => {
const [extension] = installed.filter(e => getId(e.manifest) === id);
if (!extension) {
......
......@@ -135,7 +135,13 @@ export interface IGalleryMetadata {
publisherDisplayName: string;
}
export enum LocalExtensionType {
System,
User
}
export interface ILocalExtension {
type: LocalExtensionType;
id: string;
manifest: IExtensionManifest;
metadata: IGalleryMetadata;
......@@ -205,7 +211,7 @@ export interface IExtensionManagementService {
install(zipPath: string): TPromise<void>;
installFromGallery(extension: IGalleryExtension): TPromise<void>;
uninstall(extension: ILocalExtension): TPromise<void>;
getInstalled(): TPromise<ILocalExtension[]>;
getInstalled(type?: LocalExtensionType): TPromise<ILocalExtension[]>;
}
export const IExtensionTipsService = createDecorator<IExtensionTipsService>('extensionTipsService');
......
......@@ -7,7 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension } from './extensionManagement';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType } from './extensionManagement';
import Event, { buffer } from 'vs/base/common/event';
export interface IExtensionManagementChannel extends IChannel {
......@@ -45,7 +45,7 @@ export class ExtensionManagementChannel implements IExtensionManagementChannel {
case 'install': return this.service.install(arg);
case 'installFromGallery': return this.service.installFromGallery(arg);
case 'uninstall': return this.service.uninstall(arg);
case 'getInstalled': return this.service.getInstalled();
case 'getInstalled': return this.service.getInstalled(arg);
}
}
}
......@@ -80,7 +80,7 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
return this.channel.call('uninstall', extension);
}
getInstalled(): TPromise<ILocalExtension[]> {
return this.channel.call('getInstalled');
getInstalled(type: LocalExtensionType = null): TPromise<ILocalExtension[]> {
return this.channel.call('getInstalled', type);
}
}
\ No newline at end of file
......@@ -13,7 +13,10 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { flatten } from 'vs/base/common/arrays';
import { extract, buffer } from 'vs/base/node/zip';
import { Promise, TPromise } from 'vs/base/common/winjs.base';
import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IExtensionIdentity, IExtensionManifest, IGalleryMetadata, InstallExtensionEvent, DidInstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension,
IGalleryExtension, IExtensionIdentity, IExtensionManifest, IGalleryMetadata,
InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Limiter } from 'vs/base/common/async';
import Event, { Emitter } from 'vs/base/common/event';
......@@ -21,6 +24,8 @@ import * as semver from 'semver';
import { groupBy, values } from 'vs/base/common/collections';
import URI from 'vs/base/common/uri';
const SystemExtensionsRoot = path.normalize(path.join(URI.parse(require.toUrl('')).fsPath, '..', 'extensions'));
function parseManifest(raw: string): TPromise<{ manifest: IExtensionManifest; metadata: IGalleryMetadata; }> {
return new Promise((c, e) => {
try {
......@@ -149,11 +154,11 @@ export class ExtensionManagementService implements IExtensionManagementService {
return pfs.readdir(extensionPath).then(children => {
const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0];
const readmeUrl = readme ? URI.file(path.join(extensionPath, readme)).toString() : null;
const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0];
const changelogUrl = changelog ? URI.file(path.join(extensionPath, changelog)).toString() : null;
const type = LocalExtensionType.User;
const local: ILocalExtension = { id, manifest, metadata, path: extensionPath, readmeUrl, changelogUrl };
const local: ILocalExtension = { type, id, manifest, metadata, path: extensionPath, readmeUrl, changelogUrl };
const rawManifest = assign(manifest, { __metadata: metadata });
return pfs.writeFile(manifestPath, JSON.stringify(rawManifest, null, '\t'))
......@@ -163,7 +168,7 @@ export class ExtensionManagementService implements IExtensionManagementService {
}
uninstall(extension: ILocalExtension): TPromise<void> {
return this.getAllInstalled().then<void>(installed => {
return this.scanUserExtensions().then<void>(installed => {
const promises = installed
.filter(e => e.manifest.publisher === extension.manifest.publisher && e.manifest.name === extension.manifest.name)
.map(({ id }) => this.uninstallExtension(id));
......@@ -184,33 +189,50 @@ export class ExtensionManagementService implements IExtensionManagementService {
.then(() => this._onDidUninstallExtension.fire(id));
}
getInstalled(): TPromise<ILocalExtension[]> {
return this.getAllInstalled().then(extensions => {
getInstalled(type: LocalExtensionType = null): TPromise<ILocalExtension[]> {
const promises = [];
if (type === null || type === LocalExtensionType.System) {
promises.push(this.scanSystemExtensions());
}
if (type === null || type === LocalExtensionType.User) {
promises.push(this.scanUserExtensions());
}
return TPromise.join(promises).then(flatten);
}
private scanSystemExtensions(): TPromise<ILocalExtension[]> {
return this.scanExtensions(SystemExtensionsRoot, LocalExtensionType.System);
}
private scanUserExtensions(): TPromise<ILocalExtension[]> {
return this.scanExtensions(this.extensionsPath, LocalExtensionType.User).then(extensions => {
const byId = values(groupBy(extensions, p => `${ p.manifest.publisher }.${ p.manifest.name }`));
return byId.map(p => p.sort((a, b) => semver.rcompare(a.manifest.version, b.manifest.version))[0]);
});
}
private getAllInstalled(): TPromise<ILocalExtension[]> {
private scanExtensions(root: string, type: LocalExtensionType): TPromise<ILocalExtension[]> {
const limiter = new Limiter(10);
return this.getObsoleteExtensions()
.then(obsolete => {
return pfs.readdir(this.extensionsPath)
return pfs.readdir(root)
.then(extensions => extensions.filter(id => !obsolete[id]))
.then<ILocalExtension[]>(extensionIds => Promise.join(extensionIds.map(id => {
const extensionPath = path.join(this.extensionsPath, id);
const extensionPath = path.join(root, id);
const each = () => pfs.readdir(extensionPath).then(children => {
const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0];
const readmeUrl = readme ? URI.file(path.join(extensionPath, readme)).toString() : null;
const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0];
const changelogUrl = changelog ? URI.file(path.join(extensionPath, changelog)).toString() : null;
return pfs.readFile(path.join(extensionPath, 'package.json'), 'utf8')
.then(raw => parseManifest(raw))
.then<ILocalExtension>(({ manifest, metadata }) => ({ id, manifest, metadata, path: extensionPath, readmeUrl, changelogUrl }));
.then<ILocalExtension>(({ manifest, metadata }) => ({ type, id, manifest, metadata, path: extensionPath, readmeUrl, changelogUrl }));
}).then(null, () => null);
return limiter.queue(each);
......@@ -237,7 +259,7 @@ export class ExtensionManagementService implements IExtensionManagementService {
}
private getOutdatedExtensionIds(): TPromise<ILocalExtension[]> {
return this.getAllInstalled()
return this.scanUserExtensions()
.then(extensions => values(groupBy(extensions, p => `${ p.manifest.publisher }.${ p.manifest.name }`)))
.then(versions => flatten(versions.map(p => p.sort((a, b) => semver.rcompare(a.manifest.version, b.manifest.version)).slice(1))));
}
......
......@@ -5,7 +5,7 @@
'use strict';
import { IExtensionIdentity, ILocalExtension, IGalleryExtension, IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionIdentity, ILocalExtension, IGalleryExtension, IExtensionManagementService, IExtensionGalleryService, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
import { TPromise } from 'vs/base/common/winjs.base';
import * as semver from 'semver';
......@@ -43,7 +43,7 @@ export function getOutdatedExtensions(extensionsService: IExtensionManagementSer
return TPromise.as([]);
}
return extensionsService.getInstalled().then(installed => {
return extensionsService.getInstalled(LocalExtensionType.User).then(installed => {
const names = installed.map(({ manifest }) => `${ manifest.publisher }.${ manifest.name }`);
if (installed.length === 0) {
......
......@@ -35,7 +35,7 @@ import { EditorOptions } from 'vs/workbench/common/editor';
import { shell } from 'electron';
import product from 'vs/platform/product';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { CombinedInstallAction, UpdateAction, EnableAction } from './extensionsActions';
import { CombinedInstallAction, UpdateAction, EnableAction, BuiltinStatusLabelAction } from './extensionsActions';
import WebView from 'vs/workbench/parts/html/browser/webview';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { Keybinding } from 'vs/base/common/keybinding';
......@@ -240,17 +240,19 @@ export class ExtensionEditor extends BaseEditor {
const ratings = this.instantiationService.createInstance(RatingsWidget, this.rating, { extension });
this.transientDisposables.push(ratings);
const builtinStatusAction = this.instantiationService.createInstance(BuiltinStatusLabelAction);
const installAction = this.instantiationService.createInstance(CombinedInstallAction);
const updateAction = this.instantiationService.createInstance(UpdateAction);
const enableAction = this.instantiationService.createInstance(EnableAction);
installAction.extension = extension;
builtinStatusAction.extension = extension;
updateAction.extension = extension;
enableAction.extension = extension;
this.extensionActionBar.clear();
this.extensionActionBar.push([enableAction, updateAction, installAction], { icon: true, label: true });
this.transientDisposables.push(enableAction, updateAction, installAction);
this.extensionActionBar.push([enableAction, updateAction, installAction, builtinStatusAction], { icon: true, label: true });
this.transientDisposables.push(enableAction, updateAction, installAction, builtinStatusAction);
this.navbar.clear();
this.navbar.onChange(this.onNavbarChange.bind(this, extension), this, this.transientDisposables);
......
......@@ -10,7 +10,7 @@ import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {TPromise as Promise} from 'vs/base/common/winjs.base';
import {Action} from 'vs/base/common/actions';
import {match} from 'vs/base/common/glob';
import {IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService} from 'vs/platform/extensionManagement/common/extensionManagement';
import {IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService, LocalExtensionType} from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionsConfiguration, ConfigurationKey } from './extensions';
import {IModelService} from 'vs/editor/common/services/modelService';
import {IStorageService, StorageScope} from 'vs/platform/storage/common/storage';
......@@ -111,7 +111,7 @@ export class ExtensionTipsService implements IExtensionTipsService {
StorageScope.GLOBAL
);
this.extensionsService.getInstalled().done(local => {
this.extensionsService.getInstalled(LocalExtensionType.User).done(local => {
Object.keys(this.importantRecommendations)
.filter(id => this.importantRecommendationsIgnoreList.indexOf(id) === -1)
.filter(id => local.every(local => `${local.manifest.publisher}.${local.manifest.name}` !== id))
......@@ -156,7 +156,7 @@ export class ExtensionTipsService implements IExtensionTipsService {
return;
}
this.extensionsService.getInstalled().done(local => {
this.extensionsService.getInstalled(LocalExtensionType.User).done(local => {
const recommendations = allRecommendations
.filter(id => local.every(local => `${local.manifest.publisher}.${local.manifest.name}` !== id));
......
......@@ -8,7 +8,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
import Event from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { IPager } from 'vs/base/common/paging';
import { IQueryOptions, IExtensionManifest } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IQueryOptions, IExtensionManifest, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
export const VIEWLET_ID = 'workbench.view.extensions';
......@@ -24,6 +24,7 @@ export enum ExtensionState {
}
export interface IExtension {
type: LocalExtensionType;
state: ExtensionState;
name: string;
displayName: string;
......
......@@ -13,6 +13,7 @@ import Event from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions';
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, ConfigurationKey } from './extensions';
import { LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IMessageService, LaterAction } from 'vs/platform/message/common/message';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
......@@ -32,6 +33,10 @@ export class InstallAction extends Action {
private static InstallLabel = localize('installAction', "Install");
private static InstallingLabel = localize('installing', "Installing");
private static Class = 'extension-action install';
private static InstallingClass = 'extension-action install installing';
private disposables: IDisposable[] = [];
private _extension: IExtension;
get extension(): IExtension { return this._extension; }
......@@ -40,21 +45,29 @@ export class InstallAction extends Action {
constructor(
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService
) {
super('extensions.install', InstallAction.InstallLabel, 'extension-action install', false);
super('extensions.install', InstallAction.InstallLabel, InstallAction.Class, false);
this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
this.update();
}
private update(): void {
if (!this.extension) {
if (!this.extension || this.extension.type === LocalExtensionType.System) {
this.enabled = false;
this.class = InstallAction.Class;
this.label = InstallAction.InstallLabel;
return;
}
this.enabled = this.extensionsWorkbenchService.canInstall(this.extension) && this.extension.state === ExtensionState.Uninstalled;
this.label = this.extension.state === ExtensionState.Installing ? InstallAction.InstallingLabel : InstallAction.InstallLabel;
if (this.extension.state === ExtensionState.Installing) {
this.label = InstallAction.InstallingLabel;
this.class = InstallAction.InstallingClass;
} else {
this.label = InstallAction.InstallLabel;
this.class = InstallAction.Class;
}
}
run(): TPromise<any> {
......@@ -91,8 +104,12 @@ export class UninstallAction extends Action {
return;
}
this.enabled = this.extension.state === ExtensionState.Installed
|| this.extension.state === ExtensionState.NeedsRestart;
if (this.extension.type !== LocalExtensionType.User) {
this.enabled = false;
return;
}
this.enabled = this.extension.state === ExtensionState.Installed || this.extension.state === ExtensionState.NeedsRestart;
}
run(): TPromise<any> {
......@@ -143,7 +160,7 @@ export class CombinedInstallAction extends Action {
}
private update(): void {
if (!this.extension) {
if (!this.extension || this.extension.type === LocalExtensionType.System) {
this.enabled = false;
this.class = CombinedInstallAction.NoExtensionClass;
} else if (this.installAction.enabled) {
......@@ -207,6 +224,12 @@ export class UpdateAction extends Action {
return;
}
if (this.extension.type !== LocalExtensionType.User) {
this.enabled = false;
this.class = UpdateAction.DisabledClass;
return;
}
const canInstall = this.extensionsWorkbenchService.canInstall(this.extension);
const isInstalled = this.extension.state === ExtensionState.Installed
|| this.extension.state === ExtensionState.NeedsRestart;
......@@ -291,9 +314,12 @@ export class UpdateAllAction extends Action {
private get outdated(): IExtension[] {
return this.extensionsWorkbenchService.local
.filter(e => this.extensionsWorkbenchService.canInstall(e)
.filter(e =>
this.extensionsWorkbenchService.canInstall(e)
&& e.type === LocalExtensionType.User
&& (e.state === ExtensionState.Installed || e.state === ExtensionState.NeedsRestart)
&& e.outdated);
&& e.outdated
);
}
private update(): void {
......@@ -396,7 +422,6 @@ export class ShowOutdatedExtensionsAction extends Action {
}
run(): TPromise<void> {
return this.viewletService.openViewlet(VIEWLET_ID, true)
.then(viewlet => viewlet as IExtensionsViewlet)
.then(viewlet => {
......@@ -636,4 +661,29 @@ export class InstallVSIXAction extends Action {
return TPromise.join(result.map(vsix => this.extensionsWorkbenchService.install(vsix)));
}
}
\ No newline at end of file
}
export class BuiltinStatusLabelAction extends Action {
private static Class = 'extension-action built-in-status';
private _extension: IExtension;
get extension(): IExtension { return this._extension; }
set extension(extension: IExtension) { this._extension = extension; this.update(); }
constructor() {
super('extensions.install', localize('builtin', "Built-in"), '', false);
}
private update(): void {
if (this.extension && this.extension.type === LocalExtensionType.System) {
this.class = `${ BuiltinStatusLabelAction.Class } system`;
} else {
this.class = `${ BuiltinStatusLabelAction.Class } user`;
}
}
run(): TPromise<any> {
return TPromise.as(null);
}
}
......@@ -15,7 +15,7 @@ import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
import { once } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { IExtension } from './extensions';
import { CombinedInstallAction, UpdateAction, EnableAction } from './extensionsActions';
import { CombinedInstallAction, UpdateAction, EnableAction, BuiltinStatusLabelAction } from './extensionsActions';
import { Label, RatingsWidget, InstallWidget } from './extensionsWidgets';
import { EventType } from 'vs/base/common/events';
......@@ -68,12 +68,13 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
const installCountWidget = this.instantiationService.createInstance(InstallWidget, installCount, { small: true });
const ratingsWidget = this.instantiationService.createInstance(RatingsWidget, ratings, { small: true });
const builtinStatusAction = this.instantiationService.createInstance(BuiltinStatusLabelAction);
const installAction = this.instantiationService.createInstance(CombinedInstallAction);
const updateAction = this.instantiationService.createInstance(UpdateAction);
const restartAction = this.instantiationService.createInstance(EnableAction);
actionbar.push([restartAction, updateAction, installAction], actionOptions);
const disposables = [versionWidget, installCountWidget, ratingsWidget, installAction, updateAction, restartAction, actionbar];
actionbar.push([restartAction, updateAction, installAction, builtinStatusAction], actionOptions);
const disposables = [versionWidget, installCountWidget, ratingsWidget, installAction, builtinStatusAction, updateAction, restartAction, actionbar];
return {
element, icon, name, installCount, ratings, author, description, disposables,
......@@ -82,6 +83,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
versionWidget.extension = extension;
installCountWidget.extension = extension;
ratingsWidget.extension = extension;
builtinStatusAction.extension = extension;
installAction.extension = extension;
updateAction.extension = extension;
restartAction.extension = extension;
......
......@@ -31,7 +31,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { Delegate, Renderer } from './extensionsList';
import { IExtensionsWorkbenchService, IExtension, IExtensionsViewlet, VIEWLET_ID, ExtensionState } from './extensions';
import { ShowRecommendedExtensionsAction, ShowWorkspaceRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowInstalledExtensionsAction, ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, InstallVSIXAction } from './extensionsActions';
import { IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService, SortBy, SortOrder, IQueryOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService, SortBy, SortOrder, IQueryOptions, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionsInput } from './extensionsInput';
import { Query } from '../common/extensionQuery';
import { OpenGlobalSettingsAction } from 'vs/workbench/browser/actions/openSettings';
......@@ -204,7 +204,8 @@ export class ExtensionsViewlet extends Viewlet implements IExtensionsViewlet {
private query(value: string): TPromise<PagedModel<IExtension>> {
if (!value || /@outdated/i.test(value)) {
let local = this.extensionsWorkbenchService.queryLocal();
let local = this.extensionsWorkbenchService.queryLocal()
.then(result => result.filter(e => e.type === LocalExtensionType.User));
if (/@outdated/i.test(value)) {
local = local.then(result => result.filter(e => e.outdated));
......@@ -233,20 +234,22 @@ export class ExtensionsViewlet extends Viewlet implements IExtensionsViewlet {
if (/@recommended/i.test(query.value)) {
const value = query.value.replace(/@recommended/g, '').trim().toLowerCase();
return this.extensionsWorkbenchService.queryLocal().then(local => {
const names = this.tipsService.getRecommendations()
.filter(name => local.every(ext => `${ ext.publisher }.${ ext.name }` !== name))
.filter(name => name.toLowerCase().indexOf(value) > -1);
return this.extensionsWorkbenchService.queryLocal()
.then(result => result.filter(e => e.type === LocalExtensionType.User))
.then(local => {
const names = this.tipsService.getRecommendations()
.filter(name => local.every(ext => `${ ext.publisher }.${ ext.name }` !== name))
.filter(name => name.toLowerCase().indexOf(value) > -1);
this.telemetryService.publicLog('extensionRecommendations:open', { count: names.length });
this.telemetryService.publicLog('extensionRecommendations:open', { count: names.length });
if (!names.length) {
return new PagedModel([]);
}
if (!names.length) {
return new PagedModel([]);
}
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }))
.then(result => new PagedModel(result));
});
return this.extensionsWorkbenchService.queryGallery(assign(options, { names, pageSize: names.length }))
.then(result => new PagedModel(result));
});
}
if (query.value) {
......
......@@ -18,7 +18,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IPager, mapPager, singlePagePager } from 'vs/base/common/paging';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions, IExtensionManifest,
InstallExtensionEvent, DidInstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement';
InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionTelemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
......@@ -51,6 +51,10 @@ class Extension implements IExtension {
public gallery: IGalleryExtension = null
) {}
get type(): LocalExtensionType {
return this.local ? this.local.type : null;
}
get name(): string {
return this.local ? this.local.manifest.name : this.gallery.name;
}
......
......@@ -80,8 +80,22 @@
background-color: #4294CC
}
.monaco-action-bar .action-item.disabled .action-label.extension-action.install.no-extension,
.monaco-action-bar .action-item.disabled .action-label.extension-action.install:not(.installing),
.monaco-action-bar .action-item.disabled .action-label.extension-action.update,
.monaco-action-bar .action-item.disabled .action-label.extension-action.enable {
.monaco-action-bar .action-item.disabled .action-label.extension-action.enable,
.monaco-action-bar .action-item.disabled .action-label.extension-action.built-in-status.user {
display: none;
}
.monaco-action-bar .action-item .action-label.extension-action.built-in-status {
border-radius: 4px;
border-color: #c1c1c1;
color: inherit;
background-color: transparent;
opacity: 0.9;
font-style: italic;
}
.extension-editor > .header > .details > .actions > .monaco-action-bar .action-item .action-label.extension-action.built-in-status {
font-weight: normal;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册