提交 74ae993e 编写于 作者: S Sandeep Somavarapu

Add support for multiple extension management servers

上级 36f66042
......@@ -312,6 +312,19 @@ export interface IExtensionManagementService {
updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): TPromise<ILocalExtension>;
}
export const IExtensionManagementServerService = createDecorator<IExtensionManagementServerService>('extensionManagementServerService');
export interface IExtensionManagementServer {
extensionManagementService: IExtensionManagementService;
location: URI;
}
export interface IExtensionManagementServerService {
_serviceBrand: any;
readonly extensionManagementServers: IExtensionManagementServer[];
getExtensionManagementServer(location: URI): IExtensionManagementServer;
}
export enum EnablementState {
Disabled,
WorkspaceDisabled,
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, EventMultiplexer } from 'vs/base/common/event';
import {
IExtensionManagementService, ILocalExtension, IGalleryExtension, LocalExtensionType, InstallExtensionEvent, DidInstallExtensionEvent, IExtensionIdentifier, DidUninstallExtensionEvent, IReportedExtension, IGalleryMetadata,
IExtensionManagementServerService, IExtensionManagementServer
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { flatten } from 'vs/base/common/arrays';
export class MulitExtensionManagementService implements IExtensionManagementService {
_serviceBrand: any;
onInstallExtension: Event<InstallExtensionEvent>;
onDidInstallExtension: Event<DidInstallExtensionEvent>;
onUninstallExtension: Event<IExtensionIdentifier>;
onDidUninstallExtension: Event<DidUninstallExtensionEvent>;
private readonly servers: IExtensionManagementServer[];
constructor(
servers: IExtensionManagementServer[],
@IExtensionManagementServerService private extensionManagementServerService: IExtensionManagementServerService
) {
this.servers = servers ? servers : this.extensionManagementServerService.extensionManagementServers;
this.onInstallExtension = this.servers.reduce((emitter: EventMultiplexer<InstallExtensionEvent>, server) => { emitter.add(server.extensionManagementService.onInstallExtension); return emitter; }, new EventMultiplexer<InstallExtensionEvent>()).event;
this.onDidInstallExtension = this.servers.reduce((emitter: EventMultiplexer<DidInstallExtensionEvent>, server) => { emitter.add(server.extensionManagementService.onDidInstallExtension); return emitter; }, new EventMultiplexer<DidInstallExtensionEvent>()).event;
this.onUninstallExtension = this.servers.reduce((emitter: EventMultiplexer<IExtensionIdentifier>, server) => { emitter.add(server.extensionManagementService.onUninstallExtension); return emitter; }, new EventMultiplexer<IExtensionIdentifier>()).event;
this.onDidUninstallExtension = this.servers.reduce((emitter: EventMultiplexer<DidUninstallExtensionEvent>, server) => { emitter.add(server.extensionManagementService.onDidUninstallExtension); return emitter; }, new EventMultiplexer<DidUninstallExtensionEvent>()).event;
}
getInstalled(type?: LocalExtensionType): TPromise<ILocalExtension[]> {
return TPromise.join(this.servers.map(({ extensionManagementService }) => extensionManagementService.getInstalled(type)))
.then(result => flatten(result));
}
uninstall(extension: ILocalExtension, force?: boolean): TPromise<void> {
return this.getServer(extension).extensionManagementService.uninstall(extension, force);
}
reinstallFromGallery(extension: ILocalExtension): TPromise<ILocalExtension> {
return this.getServer(extension).extensionManagementService.reinstallFromGallery(extension);
}
updateMetadata(extension: ILocalExtension, metadata: IGalleryMetadata): TPromise<ILocalExtension> {
return this.getServer(extension).extensionManagementService.updateMetadata(extension, metadata);
}
install(zipPath: string): TPromise<ILocalExtension> {
return this.servers[0].extensionManagementService.install(zipPath);
}
installFromGallery(extension: IGalleryExtension): TPromise<ILocalExtension> {
return this.servers[0].extensionManagementService.installFromGallery(extension);
}
getExtensionsReport(): TPromise<IReportedExtension[]> {
return this.servers[0].extensionManagementService.getExtensionsReport();
}
private getServer(extension: ILocalExtension): IExtensionManagementServer {
return this.extensionManagementServerService.getExtensionManagementServer(extension.location);
}
}
\ No newline at end of file
......@@ -64,7 +64,7 @@ import { getDelayedChannel, IPCClient } from 'vs/base/parts/ipc/common/ipc';
import { connect as connectNet } from 'vs/base/parts/ipc/node/ipc.net';
import { DefaultURITransformer } from 'vs/base/common/uriIpc';
import { IExtensionManagementChannel, ExtensionManagementChannelClient } from 'vs/platform/extensionManagement/common/extensionManagementIpc';
import { IExtensionManagementService, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementService, IExtensionEnablementService, IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
import { ITimerService } from 'vs/workbench/services/timer/common/timerService';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
......@@ -98,6 +98,8 @@ import { EventType, addDisposableListener, addClass, getClientArea } from 'vs/ba
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { OpenerService } from 'vs/editor/browser/services/openerService';
import { SearchHistoryService } from 'vs/workbench/services/search/node/searchHistoryService';
import { MulitExtensionManagementService } from 'vs/platform/extensionManagement/common/multiExtensionManagement';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
/**
* Services that we require for the Shell
......@@ -408,7 +410,9 @@ export class WorkbenchShell {
this.lifecycleService = lifecycleService;
const extensionManagementChannel = getDelayedChannel<IExtensionManagementChannel>(sharedProcess.then(c => c.getChannel('extensions')));
serviceCollection.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementChannelClient, extensionManagementChannel, DefaultURITransformer));
const extensionManagementChannelClient = new ExtensionManagementChannelClient(extensionManagementChannel, DefaultURITransformer);
serviceCollection.set(IExtensionManagementServerService, new SyncDescriptor(ExtensionManagementServerService, extensionManagementChannelClient));
serviceCollection.set(IExtensionManagementService, new SyncDescriptor(MulitExtensionManagementService));
const extensionEnablementService = instantiationService.createInstance(ExtensionEnablementService);
serviceCollection.set(IExtensionEnablementService, extensionEnablementService);
......
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="575" height="6px">
<style>
circle {
animation: ball 2.5s cubic-bezier(0.000, 1.000, 1.000, 0.000) infinite;
fill: #bbb;
}
#balls {
animation: balls 2.5s linear infinite;
}
#circle2 { animation-delay: 0.1s; }
#circle3 { animation-delay: 0.2s; }
#circle4 { animation-delay: 0.3s; }
#circle5 { animation-delay: 0.4s; }
@keyframes ball {
from { transform: none; }
20% { transform: none; }
80% { transform: translateX(864px); }
to { transform: translateX(864px); }
}
@keyframes balls {
from { transform: translateX(-40px); }
to { transform: translateX(30px); }
}
</style>
<g id="balls">
<circle class="circle" id="circle1" cx="-115" cy="3" r="3"/>
<circle class="circle" id="circle2" cx="-130" cy="3" r="3" />
<circle class="circle" id="circle3" cx="-145" cy="3" r="3" />
<circle class="circle" id="circle4" cx="-160" cy="3" r="3" />
<circle class="circle" id="circle5" cx="-175" cy="3" r="3" />
</g>
</svg>
\ No newline at end of file
......@@ -5,20 +5,26 @@
export class Query {
constructor(public value: string, public sortBy: string) {
constructor(public value: string, public sortBy: string, public groupBy: string) {
this.value = value.trim();
}
static parse(value: string): Query {
let sortBy = '';
value = value.replace(/@sort:(\w+)(-\w*)?/g, (match, by: string, order: string) => {
sortBy = by;
return '';
});
return new Query(value, sortBy);
let groupBy = '';
value = value.replace(/@group:(\w+)(-\w*)?/g, (match, by: string, order: string) => {
groupBy = by;
return '';
});
return new Query(value, sortBy, groupBy);
}
toString(): string {
......@@ -27,6 +33,9 @@ export class Query {
if (this.sortBy) {
result = `${result}${result ? ' ' : ''}@sort:${this.sortBy}`;
}
if (this.groupBy) {
result = `${result}${result ? ' ' : ''}@group:${this.groupBy}`;
}
return result;
}
......
......@@ -10,13 +10,18 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { EditorInput } from 'vs/workbench/common/editor';
import { IExtension } from 'vs/workbench/parts/extensions/common/extensions';
import URI from 'vs/base/common/uri';
import { IExtensionManagementServerService, IExtensionManagementServer } from 'vs/platform/extensionManagement/common/extensionManagement';
export class ExtensionsInput extends EditorInput {
static readonly ID = 'workbench.extensions.input2';
get extension(): IExtension { return this._extension; }
get servers(): IExtensionManagementServer[] { return this.extensionManagementServerService.extensionManagementServers; }
constructor(private _extension: IExtension) {
constructor(
private _extension: IExtension,
@IExtensionManagementServerService private extensionManagementServerService: IExtensionManagementServerService
) {
super();
}
......
......@@ -31,7 +31,7 @@ import { Renderer, DataSource, Controller } from 'vs/workbench/parts/extensions/
import { RatingsWidget, InstallCountWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets';
import { EditorOptions } from 'vs/workbench/common/editor';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { CombinedInstallAction, UpdateAction, EnableAction, DisableAction, ReloadAction, MaliciousStatusLabelAction, DisabledStatusLabelAction } from 'vs/workbench/parts/extensions/browser/extensionsActions';
import { CombinedInstallAction, UpdateAction, EnableAction, DisableAction, ReloadAction, MaliciousStatusLabelAction, DisabledStatusLabelAction, MultiServerInstallAction, MultiServerUpdateAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
import { WebviewElement } from 'vs/workbench/parts/webview/electron-browser/webviewElement';
import { KeybindingIO } from 'vs/workbench/services/keybinding/common/keybindingIO';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
......@@ -247,6 +247,12 @@ export class ExtensionEditor extends BaseEditor {
if (action.id === DisableAction.ID) {
return (<DisableAction>action).actionItem;
}
if (action.id === MultiServerInstallAction.ID) {
return (<MultiServerInstallAction>action).actionItem;
}
if (action.id === MultiServerUpdateAction.ID) {
return (<MultiServerUpdateAction>action).actionItem;
}
return null;
}
});
......@@ -268,6 +274,7 @@ export class ExtensionEditor extends BaseEditor {
setInput(input: ExtensionsInput, options: EditorOptions, token: CancellationToken): Thenable<void> {
this.editorLoadComplete = false;
const extension = input.extension;
const servers = input.servers;
this.transientDisposables = dispose(this.transientDisposables);
......@@ -351,8 +358,8 @@ export class ExtensionEditor extends BaseEditor {
const maliciousStatusAction = this.instantiationService.createInstance(MaliciousStatusLabelAction, true);
const disabledStatusAction = this.instantiationService.createInstance(DisabledStatusLabelAction);
const installAction = this.instantiationService.createInstance(CombinedInstallAction);
const updateAction = this.instantiationService.createInstance(UpdateAction);
const installAction = servers.length === 1 ? this.instantiationService.createInstance(CombinedInstallAction, servers[0]) : this.instantiationService.createInstance(MultiServerInstallAction);
const updateAction = servers.length === 1 ? this.instantiationService.createInstance(UpdateAction, servers[0]) : this.instantiationService.createInstance(MultiServerUpdateAction);
const enableAction = this.instantiationService.createInstance(EnableAction);
const disableAction = this.instantiationService.createInstance(DisableAction);
const reloadAction = this.instantiationService.createInstance(ReloadAction);
......
......@@ -16,7 +16,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import product from 'vs/platform/node/product';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ShowRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction, InstallRecommendedExtensionAction } from 'vs/workbench/parts/extensions/browser/extensionsActions';
import { ShowRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction, InstallRecommendedExtensionAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
import Severity from 'vs/base/common/severity';
import { IWorkspaceContextService, IWorkspaceFolder, IWorkspace, IWorkspaceFoldersChangeEvent, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { Schemas } from 'vs/base/common/network';
......
......@@ -23,7 +23,7 @@ import {
OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowRecommendedKeymapExtensionsAction, ShowPopularExtensionsAction,
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowDisabledExtensionsAction, ShowBuiltInExtensionsAction, UpdateAllAction,
EnableAllAction, EnableAllWorkpsaceAction, DisableAllAction, DisableAllWorkpsaceAction, CheckForUpdatesAction, ShowLanguageExtensionsAction, ShowAzureExtensionsAction, EnableAutoUpdateAction, DisableAutoUpdateAction, ConfigureRecommendedExtensionsCommandsContributor, OpenExtensionsFolderAction, InstallVSIXAction, ReinstallAction
} from 'vs/workbench/parts/extensions/browser/extensionsActions';
} from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput';
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { ExtensionEditor } from 'vs/workbench/parts/extensions/electron-browser/extensionEditor';
......
......@@ -15,11 +15,11 @@ 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, IExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/common/extensions';
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, extensionButtonProminentBackground, extensionButtonProminentForeground, MaliciousStatusLabelAction, DisabledStatusLabelAction } from 'vs/workbench/parts/extensions/browser/extensionsActions';
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, extensionButtonProminentBackground, extensionButtonProminentForeground, MaliciousStatusLabelAction, DisabledStatusLabelAction, MultiServerInstallAction, MultiServerUpdateAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { Label, RatingsWidget, InstallCountWidget } from 'vs/workbench/parts/extensions/browser/extensionsWidgets';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionTipsService, IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { INotificationService } from 'vs/platform/notification/common/notification';
......@@ -52,7 +52,8 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
@IExtensionsWorkbenchService private extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionService private extensionService: IExtensionService,
@IExtensionTipsService private extensionTipsService: IExtensionTipsService,
@IThemeService private themeService: IThemeService
@IThemeService private themeService: IThemeService,
@IExtensionManagementServerService private extensionManagementServerService: IExtensionManagementServerService
) { }
get templateId() { return 'extension'; }
......@@ -87,6 +88,12 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
if (action.id === ManageExtensionAction.ID) {
return (<ManageExtensionAction>action).actionItem;
}
if (action.id === MultiServerInstallAction.ID) {
return (<MultiServerInstallAction>action).actionItem;
}
if (action.id === MultiServerUpdateAction.ID) {
return (<MultiServerUpdateAction>action).actionItem;
}
return null;
}
});
......@@ -98,8 +105,10 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
const maliciousStatusAction = this.instantiationService.createInstance(MaliciousStatusLabelAction, false);
const disabledStatusAction = this.instantiationService.createInstance(DisabledStatusLabelAction);
const installAction = this.instantiationService.createInstance(InstallAction);
const updateAction = this.instantiationService.createInstance(UpdateAction);
const installAction = this.extensionManagementServerService.extensionManagementServers.length === 1 ? this.instantiationService.createInstance(InstallAction, this.extensionManagementServerService.extensionManagementServers[0])
: this.instantiationService.createInstance(MultiServerInstallAction);
const updateAction = this.extensionManagementServerService.extensionManagementServers.length === 1 ? this.instantiationService.createInstance(UpdateAction, this.extensionManagementServerService.extensionManagementServers[0])
: this.instantiationService.createInstance(MultiServerUpdateAction);
const reloadAction = this.instantiationService.createInstance(ReloadAction);
const manageAction = this.instantiationService.createInstance(ManageExtensionAction);
......@@ -141,12 +150,10 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
removeClass(data.element, 'loading');
data.extensionDisposables = dispose(data.extensionDisposables);
const isInstalled = this.extensionsWorkbenchService.local.some(e => e.id === extension.id);
this.extensionService.getExtensions().then(enabledExtensions => {
const isExtensionRunning = enabledExtensions.some(e => areSameExtensions(e, extension));
const installed = this.extensionsWorkbenchService.local.filter(e => e.id === extension.id)[0];
toggleClass(data.root, 'disabled', isInstalled && !isExtensionRunning);
this.extensionService.getExtensions().then(runningExtensions => {
toggleClass(data.root, 'disabled', installed ? runningExtensions.every(e => !(installed.local.location.toString() === e.extensionLocation.toString() && areSameExtensions(e, extension))) : false);
});
const onError = once(domEvent(data.icon, 'error'));
......
......@@ -28,11 +28,11 @@ import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, ExtensionS
import {
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction,
ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction
} from 'vs/workbench/parts/extensions/browser/extensionsActions';
import { LocalExtensionType, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction, ChangeGroupAction
} from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
import { LocalExtensionType, IExtensionManagementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput';
import { ExtensionsListView, InstalledExtensionsView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView } from './extensionsViews';
import { ExtensionsListView, InstalledExtensionsView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, GroupByServerExtensionsView } from './extensionsViews';
import { OpenGlobalSettingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
......@@ -42,7 +42,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { inputForeground, inputBackground, inputBorder } from 'vs/platform/theme/common/colorRegistry';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ViewsRegistry, IViewDescriptor } from 'vs/workbench/common/views';
import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { ViewContainerViewlet, IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IContextKeyService, ContextKeyExpr, RawContextKey, IContextKey } from 'vs/platform/contextkey/common/contextkey';
......@@ -54,6 +54,10 @@ import { IWindowService } from 'vs/platform/windows/common/windows';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
import { ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/node/extensionsWorkbenchService';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { SingleServerExtensionManagementServerService } from 'vs/workbench/services/extensions/node/extensionManagementServerService';
interface SearchInputEvent extends Event {
target: HTMLInputElement;
......@@ -66,10 +70,12 @@ const SearchInstalledExtensionsContext = new RawContextKey<boolean>('searchInsta
const SearchBuiltInExtensionsContext = new RawContextKey<boolean>('searchBuiltInExtensions', false);
const RecommendedExtensionsContext = new RawContextKey<boolean>('recommendedExtensions', false);
const DefaultRecommendedExtensionsContext = new RawContextKey<boolean>('defaultRecommendedExtensions', false);
const GroupByServersContext = new RawContextKey<boolean>('groupByServersContext', false);
export class ExtensionsViewletViewsContribution implements IWorkbenchContribution {
constructor(
@IExtensionManagementServerService private extensionManagementServerService: IExtensionManagementServerService
) {
this.registerViews();
}
......@@ -87,6 +93,13 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
viewDescriptors.push(this.createDefaultRecommendedExtensionsListViewDescriptor());
viewDescriptors.push(this.createOtherRecommendedExtensionsListViewDescriptor());
viewDescriptors.push(this.createWorkspaceRecommendedExtensionsListViewDescriptor());
if (this.extensionManagementServerService.extensionManagementServers.length > 1) {
for (const extensionManagementServer of this.extensionManagementServerService.extensionManagementServers) {
viewDescriptors.push(...this.createExtensionsViewDescriptorsForServer(extensionManagementServer));
}
}
ViewsRegistry.registerViews(viewDescriptors);
}
......@@ -96,7 +109,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('marketPlace', "Marketplace"),
container: VIEW_CONTAINER,
ctor: ExtensionsListView,
when: ContextKeyExpr.and(ContextKeyExpr.has('searchExtensions'), ContextKeyExpr.not('searchInstalledExtensions'), ContextKeyExpr.not('searchBuiltInExtensions'), ContextKeyExpr.not('recommendedExtensions')),
when: ContextKeyExpr.and(ContextKeyExpr.has('searchExtensions'), ContextKeyExpr.not('searchInstalledExtensions'), ContextKeyExpr.not('searchBuiltInExtensions'), ContextKeyExpr.not('recommendedExtensions'), ContextKeyExpr.not('groupByServersContext')),
weight: 100
};
}
......@@ -107,7 +120,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('installedExtensions', "Installed"),
container: VIEW_CONTAINER,
ctor: InstalledExtensionsView,
when: ContextKeyExpr.and(ContextKeyExpr.not('searchExtensions')),
when: ContextKeyExpr.not('searchExtensions'),
order: 1,
weight: 30,
canToggleVisibility: true,
......@@ -121,7 +134,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('enabledExtensions', "Enabled"),
container: VIEW_CONTAINER,
ctor: EnabledExtensionsView,
when: ContextKeyExpr.and(ContextKeyExpr.not('searchExtensions')),
when: ContextKeyExpr.not('searchExtensions'),
weight: 30,
canToggleVisibility: true,
order: 1
......@@ -134,10 +147,10 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('disabledExtensions', "Disabled"),
container: VIEW_CONTAINER,
ctor: DisabledExtensionsView,
when: ContextKeyExpr.and(ContextKeyExpr.not('searchExtensions')),
weight: 1,
when: ContextKeyExpr.not('searchExtensions'),
weight: 30,
canToggleVisibility: true,
order: 30,
order: 1,
hideByDefault: true
};
}
......@@ -148,11 +161,22 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('searchInstalledExtensions', "Installed"),
container: VIEW_CONTAINER,
ctor: InstalledExtensionsView,
when: ContextKeyExpr.and(ContextKeyExpr.has('searchInstalledExtensions')),
when: ContextKeyExpr.and(ContextKeyExpr.has('searchInstalledExtensions'), ContextKeyExpr.not('groupByServersContext')),
weight: 100
};
}
private createExtensionsViewDescriptorsForServer(server: IExtensionManagementServer): IViewDescriptor[] {
return [{
id: `server.extensionsList.${server.location.toString()}`,
name: server.location.authority,
container: VIEW_CONTAINER,
ctor: GroupByServerExtensionsView,
when: ContextKeyExpr.has('groupByServersContext'),
weight: 100
}];
}
private createDefaultRecommendedExtensionsListViewDescriptor(): IViewDescriptor {
return {
id: 'extensions.recommendedList',
......@@ -172,7 +196,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('otherRecommendedExtensions', "Other Recommendations"),
container: VIEW_CONTAINER,
ctor: RecommendedExtensionsView,
when: ContextKeyExpr.and(ContextKeyExpr.has('recommendedExtensions')),
when: ContextKeyExpr.has('recommendedExtensions'),
weight: 50,
canToggleVisibility: true,
order: 2
......@@ -198,7 +222,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('builtInExtensions', "Features"),
container: VIEW_CONTAINER,
ctor: BuiltInExtensionsView,
when: ContextKeyExpr.and(ContextKeyExpr.has('searchBuiltInExtensions')),
when: ContextKeyExpr.has('searchBuiltInExtensions'),
weight: 100,
canToggleVisibility: true
};
......@@ -210,7 +234,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('builtInThemesExtensions', "Themes"),
container: VIEW_CONTAINER,
ctor: BuiltInThemesExtensionsView,
when: ContextKeyExpr.and(ContextKeyExpr.has('searchBuiltInExtensions')),
when: ContextKeyExpr.has('searchBuiltInExtensions'),
weight: 100,
canToggleVisibility: true
};
......@@ -222,7 +246,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
name: localize('builtInBasicsExtensions', "Programming Languages"),
container: VIEW_CONTAINER,
ctor: BuiltInBasicsExtensionsView,
when: ContextKeyExpr.and(ContextKeyExpr.has('searchBuiltInExtensions')),
when: ContextKeyExpr.has('searchBuiltInExtensions'),
weight: 100,
canToggleVisibility: true
};
......@@ -236,6 +260,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
private searchExtensionsContextKey: IContextKey<boolean>;
private searchInstalledExtensionsContextKey: IContextKey<boolean>;
private searchBuiltInExtensionsContextKey: IContextKey<boolean>;
private groupByServersContextKey: IContextKey<boolean>;
private recommendedExtensionsContextKey: IContextKey<boolean>;
private defaultRecommendedExtensionsContextKey: IContextKey<boolean>;
......@@ -246,6 +271,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
private extensionsBox: HTMLElement;
private primaryActions: IAction[];
private secondaryActions: IAction[];
private groupByServerAction: IAction;
private disposables: IDisposable[] = [];
constructor(
......@@ -263,7 +289,8 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IContextKeyService contextKeyService: IContextKeyService,
@IContextMenuService contextMenuService: IContextMenuService,
@IExtensionService extensionService: IExtensionService
@IExtensionService extensionService: IExtensionService,
@IExtensionManagementServerService private extensionManagementServerService: IExtensionManagementServerService
) {
super(VIEWLET_ID, `${VIEWLET_ID}.state`, true, partService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
......@@ -273,6 +300,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
this.searchInstalledExtensionsContextKey = SearchInstalledExtensionsContext.bindTo(contextKeyService);
this.searchBuiltInExtensionsContextKey = SearchBuiltInExtensionsContext.bindTo(contextKeyService);
this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService);
this.groupByServersContextKey = GroupByServersContext.bindTo(contextKeyService);
this.defaultRecommendedExtensionsContextKey = DefaultRecommendedExtensionsContext.bindTo(contextKeyService);
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
this.disposables.push(this.viewletService.onDidViewletOpen(this.onViewletOpen, this, this.disposables));
......@@ -371,6 +399,12 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
getSecondaryActions(): IAction[] {
if (!this.secondaryActions) {
if (!this.groupByServerAction) {
this.groupByServerAction = this.instantiationService.createInstance(ChangeGroupAction, 'extensions.group.servers', localize('group by servers', "Group By: Server"), this.onSearchChange, 'server');
this.disposables.push(this.onSearchChange(value => {
this.groupByServerAction.enabled = !value || InstalledExtensionsView.isInstalledExtensionsQuery(value) || ExtensionsListView.isBuiltInExtensionsQuery(value);
}));
}
this.secondaryActions = [
this.instantiationService.createInstance(ShowInstalledExtensionsAction, ShowInstalledExtensionsAction.ID, ShowInstalledExtensionsAction.LABEL),
this.instantiationService.createInstance(ShowOutdatedExtensionsAction, ShowOutdatedExtensionsAction.ID, ShowOutdatedExtensionsAction.LABEL),
......@@ -384,6 +418,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.rating', localize('sort by rating', "Sort By: Rating"), this.onSearchChange, 'rating'),
this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.name', localize('sort by name', "Sort By: Name"), this.onSearchChange, 'name'),
new Separator(),
...(this.extensionManagementServerService.extensionManagementServers.length > 1 ? [this.groupByServerAction, new Separator()] : []),
this.instantiationService.createInstance(CheckForUpdatesAction, CheckForUpdatesAction.ID, CheckForUpdatesAction.LABEL),
...(this.configurationService.getValue(AutoUpdateConfigurationKey) ? [this.instantiationService.createInstance(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL)] : [this.instantiationService.createInstance(UpdateAllAction, UpdateAllAction.ID, UpdateAllAction.LABEL), this.instantiationService.createInstance(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL)]),
this.instantiationService.createInstance(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL),
......@@ -414,6 +449,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
this.searchExtensionsContextKey.set(!!value);
this.searchInstalledExtensionsContextKey.set(InstalledExtensionsView.isInstalledExtensionsQuery(value));
this.searchBuiltInExtensionsContextKey.set(ExtensionsListView.isBuiltInExtensionsQuery(value));
this.groupByServersContextKey.set(ExtensionsListView.isGroupByServersExtensionsQuery(value));
this.recommendedExtensionsContextKey.set(ExtensionsListView.isRecommendedExtensionsQuery(value));
this.nonEmptyWorkspaceContextKey.set(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY);
......@@ -428,6 +464,20 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
return addedViews;
}
protected createView(viewDescriptor: IViewDescriptor, options: IViewletViewOptions): ViewletPanel {
for (const extensionManagementServer of this.extensionManagementServerService.extensionManagementServers) {
if (viewDescriptor.id === `server.extensionsList.${extensionManagementServer.location.toString()}`) {
const servicesCollection: ServiceCollection = new ServiceCollection();
servicesCollection.set(IExtensionManagementServerService, new SingleServerExtensionManagementServerService(extensionManagementServer));
servicesCollection.set(IExtensionManagementService, extensionManagementServer.extensionManagementService);
servicesCollection.set(IExtensionsWorkbenchService, new SyncDescriptor(ExtensionsWorkbenchService));
const instantiationService = this.instantiationService.createChild(servicesCollection);
return instantiationService.createInstance(viewDescriptor.ctor, options, [extensionManagementServer]) as ViewletPanel;
}
}
return this.instantiationService.createInstance(viewDescriptor.ctor, options) as ViewletPanel;
}
private count(): number {
return this.panels.reduce((count, view) => (<ExtensionsListView>view).count() + count, 0);
}
......
......@@ -18,7 +18,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { append, $, toggleClass } from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Delegate, Renderer } from 'vs/workbench/parts/extensions/browser/extensionsList';
import { Delegate, Renderer } from 'vs/workbench/parts/extensions/electron-browser/extensionsList';
import { IExtension, IExtensionsWorkbenchService } from '../common/extensions';
import { Query } from '../common/extensionQuery';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
......@@ -31,7 +31,7 @@ import { IModeService } from 'vs/editor/common/services/modeService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction } from 'vs/workbench/parts/extensions/browser/extensionsActions';
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
import { WorkbenchPagedList } from 'vs/platform/list/browser/listService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { INotificationService } from 'vs/platform/notification/common/notification';
......@@ -545,6 +545,10 @@ export class ExtensionsListView extends ViewletPanel {
return /@installed/i.test(query);
}
static isGroupByServersExtensionsQuery(query: string): boolean {
return !!Query.parse(query).groupBy;
}
static isOutdatedExtensionsQuery(query: string): boolean {
return /@outdated/i.test(query);
}
......@@ -593,6 +597,18 @@ export class InstalledExtensionsView extends ExtensionsListView {
}
}
export class GroupByServerExtensionsView extends ExtensionsListView {
async show(query: string): TPromise<IPagedModel<IExtension>> {
query = query.replace(/@group:server/g, '').trim();
query = query ? query : '@installed';
if (!InstalledExtensionsView.isInstalledExtensionsQuery(query) && !ExtensionsListView.isBuiltInExtensionsQuery(query)) {
query = query += ' @installed';
}
return super.show(query.trim());
}
}
export class EnabledExtensionsView extends ExtensionsListView {
async show(query: string): TPromise<IPagedModel<IExtension>> {
......
......@@ -19,6 +19,8 @@
background: url('clear-inverse.svg') center center no-repeat;
}
.monaco-action-bar .action-item .action-label.extension-action.multiserver.install:after,
.monaco-action-bar .action-item .action-label.extension-action.multiserver.update:after,
.monaco-action-bar .action-item .action-label.extension-action.enable:after,
.monaco-action-bar .action-item .action-label.extension-action.disable:after {
content: '▼';
......
......@@ -36,7 +36,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { memoize } from 'vs/base/common/decorators';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { Event } from 'vs/base/common/event';
import { DisableForWorkspaceAction, DisableGloballyAction } from 'vs/workbench/parts/extensions/browser/extensionsActions';
import { DisableForWorkspaceAction, DisableGloballyAction } from 'vs/workbench/parts/extensions/electron-browser/extensionsActions';
import { INotificationService } from 'vs/platform/notification/common/notification';
export const IExtensionHostProfileService = createDecorator<IExtensionHostProfileService>('extensionHostProfileService');
......
......@@ -155,14 +155,14 @@ class Extension implements IExtension {
if (this.type === LocalExtensionType.System) {
if (this.local.manifest && this.local.manifest.contributes) {
if (Array.isArray(this.local.manifest.contributes.themes) && this.local.manifest.contributes.themes.length) {
return require.toUrl('../browser/media/theme-icon.png');
return require.toUrl('../electron-browser/media/theme-icon.png');
}
if (Array.isArray(this.local.manifest.contributes.languages) && this.local.manifest.contributes.languages.length) {
return require.toUrl('../browser/media/language-icon.png');
return require.toUrl('../electron-browser/media/language-icon.png');
}
}
}
return require.toUrl('../browser/media/defaultIcon.png');
return require.toUrl('../electron-browser/media/defaultIcon.png');
}
get repository(): string {
......@@ -241,7 +241,6 @@ class Extension implements IExtension {
if (this.type === LocalExtensionType.System) {
return TPromise.as(`# ${this.displayName || this.name}
**Notice** This is a an extension that is bundled with Visual Studio Code.
${this.description}
`);
}
......@@ -331,7 +330,6 @@ class ExtensionDependencies implements IExtensionDependencies {
export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, IURLHandler {
private static readonly SyncPeriod = 1000 * 60 * 60 * 12; // 12 hours
_serviceBrand: any;
private stateProvider: IExtensionStateProvider<ExtensionState>;
private installing: Extension[] = [];
......@@ -1009,4 +1007,4 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService,
this.syncDelayer.cancel();
this.disposables = dispose(this.disposables);
}
}
}
\ No newline at end of file
......@@ -72,72 +72,72 @@ suite('Extension query', () => {
});
test('toString', () => {
let query = new Query('hello', '');
let query = new Query('hello', '', '');
assert.equal(query.toString(), 'hello');
query = new Query('hello world', '');
query = new Query('hello world', '', '');
assert.equal(query.toString(), 'hello world');
query = new Query(' hello ', '');
query = new Query(' hello ', '', '');
assert.equal(query.toString(), 'hello');
query = new Query('', 'installs');
query = new Query('', 'installs', '');
assert.equal(query.toString(), '@sort:installs');
query = new Query('', 'installs');
query = new Query('', 'installs', '');
assert.equal(query.toString(), '@sort:installs');
query = new Query('', 'installs');
query = new Query('', 'installs', '');
assert.equal(query.toString(), '@sort:installs');
query = new Query('hello', 'installs');
query = new Query('hello', 'installs', '');
assert.equal(query.toString(), 'hello @sort:installs');
query = new Query(' hello ', 'installs');
query = new Query(' hello ', 'installs', '');
assert.equal(query.toString(), 'hello @sort:installs');
});
test('isValid', () => {
let query = new Query('hello', '');
let query = new Query('hello', '', '');
assert(query.isValid());
query = new Query('hello world', '');
query = new Query('hello world', '', '');
assert(query.isValid());
query = new Query(' hello ', '');
query = new Query(' hello ', '', '');
assert(query.isValid());
query = new Query('', 'installs');
query = new Query('', 'installs', '');
assert(query.isValid());
query = new Query('', 'installs');
query = new Query('', 'installs', '');
assert(query.isValid());
query = new Query('', 'installs');
query = new Query('', 'installs', '');
assert(query.isValid());
query = new Query('', 'installs');
query = new Query('', 'installs', '');
assert(query.isValid());
query = new Query('hello', 'installs');
query = new Query('hello', 'installs', '');
assert(query.isValid());
query = new Query(' hello ', 'installs');
query = new Query(' hello ', 'installs', '');
assert(query.isValid());
});
test('equals', () => {
let query1 = new Query('hello', '');
let query2 = new Query('hello', '');
let query1 = new Query('hello', '', '');
let query2 = new Query('hello', '', '');
assert(query1.equals(query2));
query2 = new Query('hello world', '');
query2 = new Query('hello world', '', '');
assert(!query1.equals(query2));
query2 = new Query('hello', 'installs');
query2 = new Query('hello', 'installs', '');
assert(!query1.equals(query2));
query2 = new Query('hello', 'installs');
query2 = new Query('hello', 'installs', '');
assert(!query1.equals(query2));
});
});
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IExtensionManagementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/platform/extensionManagement/common/extensionManagement';
import URI from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
export class ExtensionManagementServerService implements IExtensionManagementServerService {
_serviceBrand: any;
readonly extensionManagementServers: IExtensionManagementServer[];
constructor(
localExtensionManagementService: IExtensionManagementService
) {
this.extensionManagementServers = [{ extensionManagementService: localExtensionManagementService, location: URI.from({ scheme: 'vscode-local', authority: 'local' }) }];
}
getExtensionManagementServer(location: URI): IExtensionManagementServer {
return this.extensionManagementServers[0];
}
}
export class SingleServerExtensionManagementServerService implements IExtensionManagementServerService {
_serviceBrand: any;
readonly extensionManagementServers: IExtensionManagementServer[];
constructor(
extensionManagementServer: IExtensionManagementServer
) {
this.extensionManagementServers = [extensionManagementServer];
}
getExtensionManagementServer(location: URI): IExtensionManagementServer {
location = location.scheme === Schemas.file ? URI.from({ scheme: 'vscode-local', authority: 'local' }) : location;
return this.extensionManagementServers.filter(server => location.authority === server.location.authority)[0];
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册