Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)
* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 * disable strict null check
1143
src/vs/workbench/contrib/extensions/browser/extensionEditor.ts
Normal file
3214
src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class ExtensionActivationProgress implements IWorkbenchContribution {
|
||||
|
||||
private readonly _listener: IDisposable;
|
||||
|
||||
constructor(
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
@IProgressService progressService: IProgressService,
|
||||
@ILogService logService: ILogService,
|
||||
) {
|
||||
|
||||
const options = {
|
||||
location: ProgressLocation.Window,
|
||||
title: localize('activation', "Activating Extensions...")
|
||||
};
|
||||
|
||||
this._listener = extensionService.onWillActivateByEvent(e => {
|
||||
logService.trace('onWillActivateByEvent: ', e.event);
|
||||
progressService.withProgress(options, _ => Promise.race([e.activation, timeout(5000)]));
|
||||
});
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._listener.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { values } from 'vs/base/common/map';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
export class ExtensionDependencyChecker extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IWindowService private readonly windowService: IWindowService
|
||||
) {
|
||||
super();
|
||||
CommandsRegistry.registerCommand('workbench.extensions.installMissingDepenencies', () => this.installMissingDependencies());
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
command: {
|
||||
id: 'workbench.extensions.installMissingDepenencies',
|
||||
category: localize('extensions', "Extensions"),
|
||||
title: localize('auto install missing deps', "Install Missing Dependencies")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async getUninstalledMissingDependencies(): Promise<string[]> {
|
||||
const allMissingDependencies = await this.getAllMissingDependencies();
|
||||
const localExtensions = await this.extensionsWorkbenchService.queryLocal();
|
||||
return allMissingDependencies.filter(id => localExtensions.every(l => !areSameExtensions(l.identifier, { id })));
|
||||
}
|
||||
|
||||
private async getAllMissingDependencies(): Promise<string[]> {
|
||||
const runningExtensions = await this.extensionService.getExtensions();
|
||||
const runningExtensionsIds: Set<string> = runningExtensions.reduce((result, r) => { result.add(r.identifier.value.toLowerCase()); return result; }, new Set<string>());
|
||||
const missingDependencies: Set<string> = new Set<string>();
|
||||
for (const extension of runningExtensions) {
|
||||
if (extension.extensionDependencies) {
|
||||
extension.extensionDependencies.forEach(dep => {
|
||||
if (!runningExtensionsIds.has(dep.toLowerCase())) {
|
||||
missingDependencies.add(dep);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return values(missingDependencies);
|
||||
}
|
||||
|
||||
private async installMissingDependencies(): Promise<void> {
|
||||
const missingDependencies = await this.getUninstalledMissingDependencies();
|
||||
if (missingDependencies.length) {
|
||||
const extensions = (await this.extensionsWorkbenchService.queryGallery({ names: missingDependencies, pageSize: missingDependencies.length }, CancellationToken.None)).firstPage;
|
||||
if (extensions.length) {
|
||||
await Promise.all(extensions.map(extension => this.extensionsWorkbenchService.install(extension)));
|
||||
this.notificationService.notify({
|
||||
severity: Severity.Info,
|
||||
message: localize('finished installing missing deps', "Finished installing missing dependencies. Please reload the window now."),
|
||||
actions: {
|
||||
primary: [new Action('realod', localize('reload', "Realod Window"), '', true,
|
||||
() => this.windowService.reloadWindow())]
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.notificationService.info(localize('no missing deps', "There are no missing dependencies to install."));
|
||||
}
|
||||
}
|
||||
}
|
||||
210
src/vs/workbench/contrib/extensions/browser/extensionsList.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { append, $, addClass, removeClass, toggleClass } from 'vs/base/browser/dom';
|
||||
import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, ExtensionActionViewItem, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction, DisabledLabelAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { Label, RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, TooltipWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export interface IExtensionsViewState {
|
||||
onFocus: Event<IExtension>;
|
||||
onBlur: Event<IExtension>;
|
||||
}
|
||||
|
||||
export interface ITemplateData {
|
||||
root: HTMLElement;
|
||||
element: HTMLElement;
|
||||
icon: HTMLImageElement;
|
||||
name: HTMLElement;
|
||||
// {{SQL CARBON EDIT}}
|
||||
//installCount: HTMLElement;
|
||||
//ratings: HTMLElement;
|
||||
author: HTMLElement;
|
||||
description: HTMLElement;
|
||||
extension: IExtension | null;
|
||||
disposables: IDisposable[];
|
||||
extensionDisposables: IDisposable[];
|
||||
actionbar: ActionBar;
|
||||
}
|
||||
|
||||
export class Delegate implements IListVirtualDelegate<IExtension> {
|
||||
getHeight() { return 62; }
|
||||
getTemplateId() { return 'extension'; }
|
||||
}
|
||||
|
||||
const actionOptions = { icon: true, label: true, tabOnlyOnFocus: true };
|
||||
|
||||
export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
|
||||
|
||||
constructor(
|
||||
private extensionViewState: IExtensionsViewState,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService
|
||||
) { }
|
||||
|
||||
get templateId() { return 'extension'; }
|
||||
|
||||
renderTemplate(root: HTMLElement): ITemplateData {
|
||||
const recommendationWidget = this.instantiationService.createInstance(RecommendationWidget, root);
|
||||
const element = append(root, $('.extension'));
|
||||
const iconContainer = append(element, $('.icon-container'));
|
||||
const icon = append(iconContainer, $<HTMLImageElement>('img.icon'));
|
||||
const iconRemoteBadgeWidget = this.instantiationService.createInstance(RemoteBadgeWidget, iconContainer, false);
|
||||
const details = append(element, $('.details'));
|
||||
const headerContainer = append(details, $('.header-container'));
|
||||
const header = append(headerContainer, $('.header'));
|
||||
const name = append(header, $('span.name'));
|
||||
const version = append(header, $('span.version'));
|
||||
const installCount = append(header, $('span.install-count'));
|
||||
const ratings = append(header, $('span.ratings'));
|
||||
const headerRemoteBadgeWidget = this.instantiationService.createInstance(RemoteBadgeWidget, header, false);
|
||||
const description = append(details, $('.description.ellipsis'));
|
||||
const footer = append(details, $('.footer'));
|
||||
const author = append(footer, $('.author.ellipsis'));
|
||||
const actionbar = new ActionBar(footer, {
|
||||
animated: false,
|
||||
actionViewItemProvider: (action: Action) => {
|
||||
if (action.id === ManageExtensionAction.ID) {
|
||||
return (<ManageExtensionAction>action).createActionViewItem();
|
||||
}
|
||||
return new ExtensionActionViewItem(null, action, actionOptions);
|
||||
}
|
||||
});
|
||||
actionbar.onDidRun(({ error }) => error && this.notificationService.error(error));
|
||||
|
||||
const systemDisabledWarningAction = this.instantiationService.createInstance(SystemDisabledWarningAction);
|
||||
const reloadAction = this.instantiationService.createInstance(ReloadAction);
|
||||
const actions = [
|
||||
this.instantiationService.createInstance(StatusLabelAction),
|
||||
this.instantiationService.createInstance(UpdateAction),
|
||||
reloadAction,
|
||||
this.instantiationService.createInstance(InstallAction),
|
||||
this.instantiationService.createInstance(RemoteInstallAction),
|
||||
this.instantiationService.createInstance(LocalInstallAction),
|
||||
this.instantiationService.createInstance(MaliciousStatusLabelAction, false),
|
||||
systemDisabledWarningAction,
|
||||
this.instantiationService.createInstance(ManageExtensionAction)
|
||||
];
|
||||
const disabledLabelAction = this.instantiationService.createInstance(DisabledLabelAction, systemDisabledWarningAction);
|
||||
const tooltipWidget = this.instantiationService.createInstance(TooltipWidget, root, disabledLabelAction, recommendationWidget, reloadAction);
|
||||
const widgets = [
|
||||
recommendationWidget,
|
||||
iconRemoteBadgeWidget,
|
||||
headerRemoteBadgeWidget,
|
||||
tooltipWidget,
|
||||
this.instantiationService.createInstance(Label, version, (e: IExtension) => e.version),
|
||||
// {{SQL CARBON EDIT}}
|
||||
// this.instantiationService.createInstance(InstallCountWidget, installCount, true),
|
||||
this.instantiationService.createInstance(RatingsWidget, ratings, true)
|
||||
];
|
||||
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets, disabledLabelAction]);
|
||||
|
||||
actionbar.push(actions, actionOptions);
|
||||
const disposables = combinedDisposable(...actions, ...widgets, actionbar, extensionContainers, disabledLabelAction);
|
||||
|
||||
return {
|
||||
// {{SQL CARBON EDIT}}
|
||||
root, element, icon, name, /*installCount, ratings,*/ author, description, disposables: [disposables], actionbar,
|
||||
extensionDisposables: [],
|
||||
set extension(extension: IExtension) {
|
||||
extensionContainers.extension = extension;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
renderPlaceholder(index: number, data: ITemplateData): void {
|
||||
addClass(data.element, 'loading');
|
||||
|
||||
data.root.removeAttribute('aria-label');
|
||||
data.extensionDisposables = dispose(data.extensionDisposables);
|
||||
data.icon.src = '';
|
||||
data.name.textContent = '';
|
||||
data.author.textContent = '';
|
||||
data.description.textContent = '';
|
||||
// {{SQL CARBON EDIT}}
|
||||
//data.installCount.style.display = 'none';
|
||||
//data.ratings.style.display = 'none';
|
||||
data.extension = null;
|
||||
}
|
||||
|
||||
renderElement(extension: IExtension, index: number, data: ITemplateData): void {
|
||||
removeClass(data.element, 'loading');
|
||||
|
||||
if (extension.state !== ExtensionState.Uninstalled && !extension.server) {
|
||||
// Get the extension if it is installed and has no server information
|
||||
extension = this.extensionsWorkbenchService.local.filter(e => e.server === extension.server && areSameExtensions(e.identifier, extension.identifier))[0] || extension;
|
||||
}
|
||||
|
||||
data.extensionDisposables = dispose(data.extensionDisposables);
|
||||
|
||||
const updateEnablement = async () => {
|
||||
const runningExtensions = await this.extensionService.getExtensions();
|
||||
if (extension.local && !isLanguagePackExtension(extension.local.manifest)) {
|
||||
const runningExtension = runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, extension.identifier))[0];
|
||||
const isSameExtensionRunning = runningExtension && extension.server === this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation);
|
||||
toggleClass(data.root, 'disabled', !isSameExtensionRunning);
|
||||
} else {
|
||||
removeClass(data.root, 'disabled');
|
||||
}
|
||||
};
|
||||
updateEnablement();
|
||||
this.extensionService.onDidChangeExtensions(() => updateEnablement(), this, data.extensionDisposables);
|
||||
|
||||
const onError = Event.once(domEvent(data.icon, 'error'));
|
||||
onError(() => data.icon.src = extension.iconUrlFallback, null, data.extensionDisposables);
|
||||
data.icon.src = extension.iconUrl;
|
||||
|
||||
if (!data.icon.complete) {
|
||||
data.icon.style.visibility = 'hidden';
|
||||
data.icon.onload = () => data.icon.style.visibility = 'inherit';
|
||||
} else {
|
||||
data.icon.style.visibility = 'inherit';
|
||||
}
|
||||
|
||||
data.name.textContent = extension.displayName;
|
||||
data.author.textContent = extension.publisherDisplayName;
|
||||
data.description.textContent = extension.description;
|
||||
// {{SQL CARBON EDIT}}
|
||||
//data.installCount.style.display = '';
|
||||
//data.ratings.style.display = '';
|
||||
data.extension = extension;
|
||||
|
||||
if (extension.gallery && extension.gallery.properties && extension.gallery.properties.localizedLanguages && extension.gallery.properties.localizedLanguages.length) {
|
||||
data.description.textContent = extension.gallery.properties.localizedLanguages.map(name => name[0].toLocaleUpperCase() + name.slice(1)).join(', ');
|
||||
}
|
||||
|
||||
this.extensionViewState.onFocus(e => {
|
||||
if (areSameExtensions(extension.identifier, e.identifier)) {
|
||||
data.actionbar.viewItems.forEach(item => (<ExtensionActionViewItem>item).setFocus(true));
|
||||
}
|
||||
}, this, data.extensionDisposables);
|
||||
|
||||
this.extensionViewState.onBlur(e => {
|
||||
if (areSameExtensions(extension.identifier, e.identifier)) {
|
||||
data.actionbar.viewItems.forEach(item => (<ExtensionActionViewItem>item).setFocus(false));
|
||||
}
|
||||
}, this, data.extensionDisposables);
|
||||
}
|
||||
|
||||
disposeTemplate(data: ITemplateData): void {
|
||||
data.disposables = dispose(data.disposables);
|
||||
}
|
||||
}
|
||||
@@ -255,8 +255,10 @@ export class ExtensionData implements IExtensionData {
|
||||
toQuery.push(id);
|
||||
}
|
||||
}
|
||||
const galleryResult = await this.extensionsWorkbenchService.queryGallery({ names: this.childrenExtensionIds, pageSize: this.childrenExtensionIds.length }, CancellationToken.None);
|
||||
result.push(...galleryResult.firstPage);
|
||||
if (toQuery.length) {
|
||||
const galleryResult = await this.extensionsWorkbenchService.queryGallery({ names: toQuery, pageSize: toQuery.length }, CancellationToken.None);
|
||||
result.push(...galleryResult.firstPage);
|
||||
}
|
||||
return result.map(extension => new ExtensionData(extension, this, this.getChildrenExtensionIds, this.extensionsWorkbenchService));
|
||||
}
|
||||
return null;
|
||||
|
||||
697
src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts
Normal file
@@ -0,0 +1,697 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/extensionsViewlet';
|
||||
import { localize } from 'vs/nls';
|
||||
import { timeout, Delayer } from 'vs/base/common/async';
|
||||
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Event as EventOf, Emitter } from 'vs/base/common/event';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IViewlet } from 'vs/workbench/common/viewlet';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { append, $, addClass, toggleClass, Dimension } from 'vs/base/browser/dom';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, ExtensionState, AutoUpdateConfigurationKey, ShowRecommendationsOnlyOnDemandKey, CloseExtensionDetailsOnViewChangeKey, VIEW_CONTAINER } from '../common/extensions';
|
||||
import {
|
||||
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction,
|
||||
ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
|
||||
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction
|
||||
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IExtensionManagementService, IExtensionManagementServerService, IExtensionManagementServer, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
|
||||
import { OpenGlobalSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IActivityService, ProgressBadge, NumberBadge } from 'vs/workbench/services/activity/common/activity';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IViewsRegistry, IViewDescriptor, Extensions } from 'vs/workbench/common/views';
|
||||
import { IStorageService, StorageScope } 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';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
|
||||
import { ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
|
||||
import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery';
|
||||
import { SuggestEnabledInput, attachSuggestEnabledInputBoxStyler } from 'vs/workbench/contrib/codeEditor/browser/suggestEnabledInput/suggestEnabledInput';
|
||||
import { alert } from 'vs/base/browser/ui/aria/aria';
|
||||
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||
import { RemoteAuthorityContext } from 'vs/workbench/browser/contextkeys';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { MementoObject } from 'vs/workbench/common/memento';
|
||||
|
||||
interface SearchInputEvent extends Event {
|
||||
target: HTMLInputElement;
|
||||
immediate?: boolean;
|
||||
}
|
||||
|
||||
const NonEmptyWorkspaceContext = new RawContextKey<boolean>('nonEmptyWorkspace', false);
|
||||
const DefaultViewsContext = new RawContextKey<boolean>('defaultExtensionViews', true);
|
||||
const SearchMarketplaceExtensionsContext = new RawContextKey<boolean>('searchMarketplaceExtensions', false);
|
||||
const SearchIntalledExtensionsContext = new RawContextKey<boolean>('searchInstalledExtensions', false);
|
||||
const SearchOutdatedExtensionsContext = new RawContextKey<boolean>('searchOutdatedExtensions', false);
|
||||
const SearchEnabledExtensionsContext = new RawContextKey<boolean>('searchEnabledExtensions', false);
|
||||
const SearchDisabledExtensionsContext = new RawContextKey<boolean>('searchDisabledExtensions', false);
|
||||
const HasInstalledExtensionsContext = new RawContextKey<boolean>('hasInstalledExtensions', true);
|
||||
const SearchBuiltInExtensionsContext = new RawContextKey<boolean>('searchBuiltInExtensions', false);
|
||||
const RecommendedExtensionsContext = new RawContextKey<boolean>('recommendedExtensions', false);
|
||||
const DefaultRecommendedExtensionsContext = new RawContextKey<boolean>('defaultRecommendedExtensions', false);
|
||||
const viewIdNameMappings: { [id: string]: string } = {
|
||||
'extensions.listView': localize('marketPlace', "Marketplace"),
|
||||
'extensions.enabledExtensionList': localize('enabledExtensions', "Enabled"),
|
||||
'extensions.enabledExtensionList2': localize('enabledExtensions', "Enabled"),
|
||||
'extensions.disabledExtensionList': localize('disabledExtensions', "Disabled"),
|
||||
'extensions.disabledExtensionList2': localize('disabledExtensions', "Disabled"),
|
||||
// {{SQL CARBON EDIT}}
|
||||
// 'extensions.popularExtensionsList': localize('popularExtensions', "Popular"),
|
||||
'extensions.recommendedList': localize('recommendedExtensions', "Recommended"),
|
||||
'extensions.otherrecommendedList': localize('otherRecommendedExtensions', "Other Recommendations"),
|
||||
'extensions.workspaceRecommendedList': localize('workspaceRecommendedExtensions', "Workspace Recommendations"),
|
||||
'extensions.builtInExtensionsList': localize('builtInExtensions', "Features"),
|
||||
'extensions.builtInThemesExtensionsList': localize('builtInThemesExtensions', "Themes"),
|
||||
'extensions.builtInBasicsExtensionsList': localize('builtInBasicsExtensions', "Programming Languages"),
|
||||
};
|
||||
|
||||
export class ExtensionsViewletViewsContribution implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService
|
||||
) {
|
||||
this.registerViews();
|
||||
}
|
||||
|
||||
private registerViews(): void {
|
||||
let viewDescriptors: IViewDescriptor[] = [];
|
||||
viewDescriptors.push(this.createMarketPlaceExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createDefaultEnabledExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createDefaultDisabledExtensionsListViewDescriptor());
|
||||
// {{SQL CARBON EDIT}}
|
||||
// viewDescriptors.push(this.createDefaultPopularExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createEnabledExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createDisabledExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createBuiltInExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createBuiltInBasicsExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createBuiltInThemesExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createDefaultRecommendedExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createOtherRecommendedExtensionsListViewDescriptor());
|
||||
viewDescriptors.push(this.createWorkspaceRecommendedExtensionsListViewDescriptor());
|
||||
|
||||
viewDescriptors.push(...this.createExtensionsViewDescriptorsForServer(this.extensionManagementServerService.localExtensionManagementServer));
|
||||
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
viewDescriptors.push(...this.createExtensionsViewDescriptorsForServer(this.extensionManagementServerService.remoteExtensionManagementServer));
|
||||
}
|
||||
|
||||
Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).registerViews(viewDescriptors, VIEW_CONTAINER);
|
||||
}
|
||||
|
||||
// View used for any kind of searching
|
||||
private createMarketPlaceExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.listView';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: ExtensionsListView },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('searchMarketplaceExtensions')),
|
||||
weight: 100
|
||||
};
|
||||
}
|
||||
|
||||
// Separate view for enabled extensions required as we need to show enabled, disabled and recommended sections
|
||||
// in the default view when there is no search text, but user has installed extensions.
|
||||
private createDefaultEnabledExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.enabledExtensionList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: EnabledExtensionsView },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), RemoteAuthorityContext.isEqualTo('')),
|
||||
weight: 40,
|
||||
canToggleVisibility: true,
|
||||
order: 1
|
||||
};
|
||||
}
|
||||
|
||||
// Separate view for disabled extensions required as we need to show enabled, disabled and recommended sections
|
||||
// in the default view when there is no search text, but user has installed extensions.
|
||||
private createDefaultDisabledExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.disabledExtensionList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: DisabledExtensionsView },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), RemoteAuthorityContext.isEqualTo('')),
|
||||
weight: 10,
|
||||
canToggleVisibility: true,
|
||||
order: 3,
|
||||
collapsed: true
|
||||
};
|
||||
}
|
||||
|
||||
/* // {{SQL CARBON EDIT}}
|
||||
// Separate view for popular extensions required as we need to show popular and recommended sections
|
||||
// in the default view when there is no search text, and user has no installed extensions.
|
||||
private createDefaultPopularExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.popularExtensionsList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: ExtensionsListView },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.not('hasInstalledExtensions')),
|
||||
weight: 60,
|
||||
order: 1
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
private createExtensionsViewDescriptorsForServer(server: IExtensionManagementServer): IViewDescriptor[] {
|
||||
const getViewName = (viewTitle: string, server: IExtensionManagementServer): string => {
|
||||
const serverLabel = this.workbenchEnvironmentService.configuration.remoteAuthority === server.authority ? this.labelService.getHostLabel(REMOTE_HOST_SCHEME, server.authority) || server.label : server.label;
|
||||
if (viewTitle && this.workbenchEnvironmentService.configuration.remoteAuthority) {
|
||||
return `${serverLabel} - ${viewTitle}`;
|
||||
}
|
||||
return viewTitle ? viewTitle : serverLabel;
|
||||
};
|
||||
const getInstalledViewName = (): string => getViewName(localize('installed', "Installed"), server);
|
||||
const getOutdatedViewName = (): string => getViewName(localize('outdated', "Outdated"), server);
|
||||
const onDidChangeServerLabel: EventOf<void> = this.workbenchEnvironmentService.configuration.remoteAuthority ? EventOf.map(this.labelService.onDidChangeFormatters, () => undefined) : EventOf.None;
|
||||
return [{
|
||||
id: `extensions.${server.authority}.installed`,
|
||||
get name() { return getInstalledViewName(); },
|
||||
ctorDescriptor: { ctor: ServerExtensionsView, arguments: [server, EventOf.map<void, string>(onDidChangeServerLabel, () => getInstalledViewName())] },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('searchInstalledExtensions')),
|
||||
weight: 100
|
||||
}, {
|
||||
id: `extensions.${server.authority}.outdated`,
|
||||
get name() { return getOutdatedViewName(); },
|
||||
ctorDescriptor: { ctor: ServerExtensionsView, arguments: [server, EventOf.map<void, string>(onDidChangeServerLabel, () => getOutdatedViewName())] },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('searchOutdatedExtensions')),
|
||||
weight: 100
|
||||
}, {
|
||||
id: `extensions.${server.authority}.default`,
|
||||
get name() { return getInstalledViewName(); },
|
||||
ctorDescriptor: { ctor: ServerExtensionsView, arguments: [server, EventOf.map<void, string>(onDidChangeServerLabel, () => getInstalledViewName())] },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), RemoteAuthorityContext.notEqualsTo('')),
|
||||
weight: 40,
|
||||
order: 1
|
||||
}];
|
||||
}
|
||||
|
||||
// Separate view for recommended extensions required as we need to show it along with other views when there is no search text.
|
||||
// When user has installed extensions, this is shown along with the views for enabled & disabled extensions
|
||||
// When user has no installed extensions, this is shown along with the view for popular extensions
|
||||
private createDefaultRecommendedExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.recommendedList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: DefaultRecommendedExtensionsView },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('defaultRecommendedExtensions')),
|
||||
weight: 40,
|
||||
order: 2,
|
||||
canToggleVisibility: true
|
||||
};
|
||||
}
|
||||
|
||||
// Separate view for recommedations that are not workspace recommendations.
|
||||
// Shown along with view for workspace recommendations, when using the command that shows recommendations
|
||||
private createOtherRecommendedExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.otherrecommendedList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: RecommendedExtensionsView },
|
||||
when: ContextKeyExpr.has('recommendedExtensions'),
|
||||
weight: 50,
|
||||
order: 2
|
||||
};
|
||||
}
|
||||
|
||||
// Separate view for workspace recommendations.
|
||||
// Shown along with view for other recommendations, when using the command that shows recommendations
|
||||
private createWorkspaceRecommendedExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.workspaceRecommendedList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: WorkspaceRecommendedExtensionsView },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('recommendedExtensions'), ContextKeyExpr.has('nonEmptyWorkspace')),
|
||||
weight: 50,
|
||||
order: 1
|
||||
};
|
||||
}
|
||||
|
||||
private createEnabledExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.enabledExtensionList2';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: EnabledExtensionsView },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('searchEnabledExtensions')),
|
||||
weight: 40,
|
||||
order: 1
|
||||
};
|
||||
}
|
||||
|
||||
private createDisabledExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.disabledExtensionList2';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: DisabledExtensionsView },
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('searchDisabledExtensions')),
|
||||
weight: 10,
|
||||
order: 3,
|
||||
collapsed: true
|
||||
};
|
||||
}
|
||||
|
||||
private createBuiltInExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.builtInExtensionsList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: BuiltInExtensionsView },
|
||||
when: ContextKeyExpr.has('searchBuiltInExtensions'),
|
||||
weight: 100
|
||||
};
|
||||
}
|
||||
|
||||
private createBuiltInThemesExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.builtInThemesExtensionsList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: BuiltInThemesExtensionsView },
|
||||
when: ContextKeyExpr.has('searchBuiltInExtensions'),
|
||||
weight: 100
|
||||
};
|
||||
}
|
||||
|
||||
private createBuiltInBasicsExtensionsListViewDescriptor(): IViewDescriptor {
|
||||
const id = 'extensions.builtInBasicsExtensionsList';
|
||||
return {
|
||||
id,
|
||||
name: viewIdNameMappings[id],
|
||||
ctorDescriptor: { ctor: BuiltInBasicsExtensionsView },
|
||||
when: ContextKeyExpr.has('searchBuiltInExtensions'),
|
||||
weight: 100
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensionsViewlet {
|
||||
|
||||
private onSearchChange: EventOf<string>;
|
||||
private nonEmptyWorkspaceContextKey: IContextKey<boolean>;
|
||||
private defaultViewsContextKey: IContextKey<boolean>;
|
||||
private searchMarketplaceExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchInstalledExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchOutdatedExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchEnabledExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchDisabledExtensionsContextKey: IContextKey<boolean>;
|
||||
private hasInstalledExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchBuiltInExtensionsContextKey: IContextKey<boolean>;
|
||||
private recommendedExtensionsContextKey: IContextKey<boolean>;
|
||||
private defaultRecommendedExtensionsContextKey: IContextKey<boolean>;
|
||||
|
||||
private searchDelayer: Delayer<void>;
|
||||
private root: HTMLElement;
|
||||
|
||||
private searchBox: SuggestEnabledInput;
|
||||
private extensionsBox: HTMLElement;
|
||||
private primaryActions: IAction[];
|
||||
private secondaryActions: IAction[] | null;
|
||||
private readonly searchViewletState: MementoObject;
|
||||
|
||||
constructor(
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IProgressService private readonly progressService: IProgressService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IWorkspaceContextService contextService: IWorkspaceContextService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IExtensionService extensionService: IExtensionService
|
||||
) {
|
||||
super(VIEWLET_ID, `${VIEWLET_ID}.state`, true, configurationService, layoutService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
|
||||
|
||||
this.searchDelayer = new Delayer(500);
|
||||
this.nonEmptyWorkspaceContextKey = NonEmptyWorkspaceContext.bindTo(contextKeyService);
|
||||
this.defaultViewsContextKey = DefaultViewsContext.bindTo(contextKeyService);
|
||||
this.searchMarketplaceExtensionsContextKey = SearchMarketplaceExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchInstalledExtensionsContextKey = SearchIntalledExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchOutdatedExtensionsContextKey = SearchOutdatedExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchEnabledExtensionsContextKey = SearchEnabledExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchDisabledExtensionsContextKey = SearchDisabledExtensionsContext.bindTo(contextKeyService);
|
||||
this.hasInstalledExtensionsContextKey = HasInstalledExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchBuiltInExtensionsContextKey = SearchBuiltInExtensionsContext.bindTo(contextKeyService);
|
||||
this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService);
|
||||
this.defaultRecommendedExtensionsContextKey = DefaultRecommendedExtensionsContext.bindTo(contextKeyService);
|
||||
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
|
||||
this._register(this.viewletService.onDidViewletOpen(this.onViewletOpen, this));
|
||||
this.searchViewletState = this.getMemento(StorageScope.WORKSPACE);
|
||||
|
||||
this.extensionManagementService.getInstalled(ExtensionType.User).then(result => {
|
||||
this.hasInstalledExtensionsContextKey.set(result.length > 0);
|
||||
});
|
||||
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(AutoUpdateConfigurationKey)) {
|
||||
this.secondaryActions = null;
|
||||
this.updateTitleArea();
|
||||
}
|
||||
if (e.affectedKeys.indexOf(ShowRecommendationsOnlyOnDemandKey) > -1) {
|
||||
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
|
||||
}
|
||||
}, this));
|
||||
}
|
||||
|
||||
create(parent: HTMLElement): void {
|
||||
addClass(parent, 'extensions-viewlet');
|
||||
this.root = parent;
|
||||
|
||||
const header = append(this.root, $('.header'));
|
||||
|
||||
const placeholder = localize('searchExtensions', "Search Extensions in Marketplace");
|
||||
const searchValue = this.searchViewletState['query.value'] ? this.searchViewletState['query.value'] : '';
|
||||
|
||||
this.searchBox = this._register(this.instantiationService.createInstance(SuggestEnabledInput, `${VIEWLET_ID}.searchbox`, header, {
|
||||
triggerCharacters: ['@'],
|
||||
sortKey: (item: string) => {
|
||||
if (item.indexOf(':') === -1) { return 'a'; }
|
||||
else if (/ext:/.test(item) || /tag:/.test(item)) { return 'b'; }
|
||||
else if (/sort:/.test(item)) { return 'c'; }
|
||||
else { return 'd'; }
|
||||
},
|
||||
provideResults: (query: string) => Query.suggestions(query)
|
||||
}, placeholder, 'extensions:searchinput', { placeholderText: placeholder, value: searchValue }));
|
||||
|
||||
if (this.searchBox.getValue()) {
|
||||
this.triggerSearch();
|
||||
}
|
||||
|
||||
this._register(attachSuggestEnabledInputBoxStyler(this.searchBox, this.themeService));
|
||||
|
||||
const _searchChange = new Emitter<string>();
|
||||
this.onSearchChange = _searchChange.event;
|
||||
this._register(this.searchBox.onInputDidChange(() => {
|
||||
this.triggerSearch();
|
||||
_searchChange.fire(this.searchBox.getValue());
|
||||
}, this));
|
||||
|
||||
this._register(this.searchBox.onShouldFocusResults(() => this.focusListView(), this));
|
||||
|
||||
this._register(this.onDidChangeVisibility(visible => {
|
||||
if (visible) {
|
||||
this.searchBox.focus();
|
||||
}
|
||||
}));
|
||||
|
||||
this.extensionsBox = append(this.root, $('.extensions'));
|
||||
super.create(this.extensionsBox);
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
this.searchBox.focus();
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): void {
|
||||
toggleClass(this.root, 'narrow', dimension.width <= 300);
|
||||
this.searchBox.layout({ height: 20, width: dimension.width - 34 });
|
||||
super.layout(new Dimension(dimension.width, dimension.height - 38));
|
||||
}
|
||||
|
||||
getOptimalWidth(): number {
|
||||
return 400;
|
||||
}
|
||||
|
||||
getActions(): IAction[] {
|
||||
if (!this.primaryActions) {
|
||||
this.primaryActions = [
|
||||
this.instantiationService.createInstance(ClearExtensionsInputAction, ClearExtensionsInputAction.ID, ClearExtensionsInputAction.LABEL, this.onSearchChange, this.searchBox.getValue())
|
||||
];
|
||||
}
|
||||
return this.primaryActions;
|
||||
}
|
||||
|
||||
getSecondaryActions(): IAction[] {
|
||||
if (!this.secondaryActions) {
|
||||
this.secondaryActions = [
|
||||
this.instantiationService.createInstance(ShowInstalledExtensionsAction, ShowInstalledExtensionsAction.ID, ShowInstalledExtensionsAction.LABEL),
|
||||
this.instantiationService.createInstance(ShowOutdatedExtensionsAction, ShowOutdatedExtensionsAction.ID, ShowOutdatedExtensionsAction.LABEL),
|
||||
this.instantiationService.createInstance(ShowEnabledExtensionsAction, ShowEnabledExtensionsAction.ID, ShowEnabledExtensionsAction.LABEL),
|
||||
this.instantiationService.createInstance(ShowDisabledExtensionsAction, ShowDisabledExtensionsAction.ID, ShowDisabledExtensionsAction.LABEL),
|
||||
this.instantiationService.createInstance(ShowBuiltInExtensionsAction, ShowBuiltInExtensionsAction.ID, ShowBuiltInExtensionsAction.LABEL),
|
||||
this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, ShowRecommendedExtensionsAction.LABEL),
|
||||
// {{SQL CARBON EDIT}}
|
||||
// this.instantiationService.createInstance(ShowPopularExtensionsAction, ShowPopularExtensionsAction.ID, ShowPopularExtensionsAction.LABEL),
|
||||
new Separator(),
|
||||
// {{SQL CARBON EDIT}}
|
||||
//this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.install', localize('sort by installs', "Sort By: Install Count"), this.onSearchChange, 'installs'),
|
||||
//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.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),
|
||||
new Separator(),
|
||||
this.instantiationService.createInstance(DisableAllAction, DisableAllAction.ID, DisableAllAction.LABEL),
|
||||
this.instantiationService.createInstance(EnableAllAction, EnableAllAction.ID, EnableAllAction.LABEL)
|
||||
];
|
||||
}
|
||||
|
||||
return this.secondaryActions;
|
||||
}
|
||||
|
||||
search(value: string): void {
|
||||
const event = new Event('input', { bubbles: true }) as SearchInputEvent;
|
||||
event.immediate = true;
|
||||
|
||||
this.searchBox.setValue(value);
|
||||
}
|
||||
|
||||
private triggerSearch(immediate = false): void {
|
||||
this.searchDelayer.trigger(() => this.doSearch(), immediate || !this.searchBox.getValue() ? 0 : 500).then(undefined, err => this.onError(err));
|
||||
}
|
||||
|
||||
private normalizedQuery(): string {
|
||||
return this.searchBox.getValue().replace(/@category/g, 'category').replace(/@tag:/g, 'tag:').replace(/@ext:/g, 'ext:');
|
||||
}
|
||||
|
||||
protected saveState(): void {
|
||||
const value = this.searchBox.getValue();
|
||||
if (ExtensionsListView.isLocalExtensionsQuery(value)) {
|
||||
this.searchViewletState['query.value'] = value;
|
||||
} else {
|
||||
this.searchViewletState['query.value'] = '';
|
||||
}
|
||||
super.saveState();
|
||||
}
|
||||
|
||||
private doSearch(): Promise<void> {
|
||||
const value = this.normalizedQuery();
|
||||
const isRecommendedExtensionsQuery = ExtensionsListView.isRecommendedExtensionsQuery(value);
|
||||
this.searchInstalledExtensionsContextKey.set(ExtensionsListView.isInstalledExtensionsQuery(value));
|
||||
this.searchOutdatedExtensionsContextKey.set(ExtensionsListView.isOutdatedExtensionsQuery(value));
|
||||
this.searchEnabledExtensionsContextKey.set(ExtensionsListView.isEnabledExtensionsQuery(value));
|
||||
this.searchDisabledExtensionsContextKey.set(ExtensionsListView.isDisabledExtensionsQuery(value));
|
||||
this.searchBuiltInExtensionsContextKey.set(ExtensionsListView.isBuiltInExtensionsQuery(value));
|
||||
this.recommendedExtensionsContextKey.set(isRecommendedExtensionsQuery);
|
||||
this.searchMarketplaceExtensionsContextKey.set(!!value && !ExtensionsListView.isLocalExtensionsQuery(value) && !isRecommendedExtensionsQuery);
|
||||
this.nonEmptyWorkspaceContextKey.set(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY);
|
||||
this.defaultViewsContextKey.set(!value);
|
||||
|
||||
return this.progress(Promise.all(this.panels.map(view =>
|
||||
(<ExtensionsListView>view).show(this.normalizedQuery())
|
||||
.then(model => this.alertSearchResult(model.length, view.id))
|
||||
))).then(() => undefined);
|
||||
}
|
||||
|
||||
protected onDidAddViews(added: IAddedViewDescriptorRef[]): ViewletPanel[] {
|
||||
const addedViews = super.onDidAddViews(added);
|
||||
this.progress(Promise.all(addedViews.map(addedView =>
|
||||
(<ExtensionsListView>addedView).show(this.normalizedQuery())
|
||||
.then(model => this.alertSearchResult(model.length, addedView.id))
|
||||
)));
|
||||
return addedViews;
|
||||
}
|
||||
|
||||
private alertSearchResult(count: number, viewId: string): void {
|
||||
switch (count) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (viewIdNameMappings[viewId]) {
|
||||
alert(localize('extensionFoundInSection', "1 extension found in the {0} section.", viewIdNameMappings[viewId]));
|
||||
} else {
|
||||
alert(localize('extensionFound', "1 extension found."));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (viewIdNameMappings[viewId]) {
|
||||
alert(localize('extensionsFoundInSection', "{0} extensions found in the {1} section.", count, viewIdNameMappings[viewId]));
|
||||
} else {
|
||||
alert(localize('extensionsFound', "{0} extensions found.", count));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private count(): number {
|
||||
return this.panels.reduce((count, view) => (<ExtensionsListView>view).count() + count, 0);
|
||||
}
|
||||
|
||||
private focusListView(): void {
|
||||
if (this.count() > 0) {
|
||||
this.panels[0].focus();
|
||||
}
|
||||
}
|
||||
|
||||
private onViewletOpen(viewlet: IViewlet): void {
|
||||
if (!viewlet || viewlet.getId() === VIEWLET_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.configurationService.getValue<boolean>(CloseExtensionDetailsOnViewChangeKey)) {
|
||||
const promises = this.editorGroupService.groups.map(group => {
|
||||
const editors = group.editors.filter(input => input instanceof ExtensionsInput);
|
||||
const promises = editors.map(editor => group.closeEditor(editor));
|
||||
|
||||
return Promise.all(promises);
|
||||
});
|
||||
|
||||
Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
||||
private progress<T>(promise: Promise<T>): Promise<T> {
|
||||
return this.progressService.withProgress({ location: ProgressLocation.Extensions }, () => promise);
|
||||
}
|
||||
|
||||
private onError(err: Error): void {
|
||||
if (isPromiseCanceledError(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = err && err.message || '';
|
||||
|
||||
if (/ECONNREFUSED/.test(message)) {
|
||||
const error = createErrorWithActions(localize('suggestProxyError', "Marketplace returned 'ECONNREFUSED'. Please check the 'http.proxy' setting."), {
|
||||
actions: [
|
||||
this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL)
|
||||
]
|
||||
});
|
||||
|
||||
this.notificationService.error(error);
|
||||
return;
|
||||
}
|
||||
|
||||
this.notificationService.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
export class StatusUpdater extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
private readonly badgeHandle = this._register(new MutableDisposable());
|
||||
|
||||
constructor(
|
||||
@IActivityService private readonly activityService: IActivityService,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService
|
||||
) {
|
||||
super();
|
||||
this._register(extensionsWorkbenchService.onChange(this.onServiceChange, this));
|
||||
}
|
||||
|
||||
private onServiceChange(): void {
|
||||
this.badgeHandle.clear();
|
||||
|
||||
if (this.extensionsWorkbenchService.local.some(e => e.state === ExtensionState.Installing)) {
|
||||
this.badgeHandle.value = this.activityService.showActivity(VIEWLET_ID, new ProgressBadge(() => localize('extensions', "Extensions")), 'extensions-badge progress-badge');
|
||||
return;
|
||||
}
|
||||
|
||||
const outdated = this.extensionsWorkbenchService.outdated.reduce((r, e) => r + (this.extensionEnablementService.isEnabled(e.local!) ? 1 : 0), 0);
|
||||
if (outdated > 0) {
|
||||
const badge = new NumberBadge(outdated, n => localize('outdatedExtensions', '{0} Outdated Extensions', n));
|
||||
this.badgeHandle.value = this.activityService.showActivity(VIEWLET_ID, badge, 'extensions-badge count-badge');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class MaliciousExtensionChecker implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@IExtensionManagementService private readonly extensionsManagementService: IExtensionManagementService,
|
||||
@IWindowService private readonly windowService: IWindowService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService
|
||||
) {
|
||||
if (!this.environmentService.disableExtensions) {
|
||||
this.loopCheckForMaliciousExtensions();
|
||||
}
|
||||
}
|
||||
|
||||
private loopCheckForMaliciousExtensions(): void {
|
||||
this.checkForMaliciousExtensions()
|
||||
.then(() => timeout(1000 * 60 * 5)) // every five minutes
|
||||
.then(() => this.loopCheckForMaliciousExtensions());
|
||||
}
|
||||
|
||||
private checkForMaliciousExtensions(): Promise<void> {
|
||||
return this.extensionsManagementService.getExtensionsReport().then(report => {
|
||||
const maliciousSet = getMaliciousExtensionsSet(report);
|
||||
|
||||
return this.extensionsManagementService.getInstalled(ExtensionType.User).then(installed => {
|
||||
const maliciousExtensions = installed
|
||||
.filter(e => maliciousSet.has(e.identifier.id));
|
||||
|
||||
if (maliciousExtensions.length) {
|
||||
return Promise.all(maliciousExtensions.map(e => this.extensionsManagementService.uninstall(e, true).then(() => {
|
||||
this.notificationService.prompt(
|
||||
Severity.Warning,
|
||||
localize('malicious warning', "We have uninstalled '{0}' which was reported to be problematic.", e.identifier.id),
|
||||
[{
|
||||
label: localize('reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
}],
|
||||
{ sticky: true }
|
||||
);
|
||||
})));
|
||||
} else {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
}).then(() => undefined);
|
||||
}, err => this.logService.error(err));
|
||||
}
|
||||
}
|
||||
1047
src/vs/workbench/contrib/extensions/browser/extensionsViews.ts
Normal file
334
src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts
Normal file
@@ -0,0 +1,334 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/extensionsWidgets';
|
||||
import { Disposable, toDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtension, IExtensionsWorkbenchService, IExtensionContainer, ExtensionState } from '../common/extensions';
|
||||
import { append, $, addClass } from 'vs/base/browser/dom';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IExtensionManagementServerService, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { extensionButtonProminentBackground, extensionButtonProminentForeground, DisabledLabelAction, ReloadAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export abstract class ExtensionWidget extends Disposable implements IExtensionContainer {
|
||||
private _extension: IExtension;
|
||||
get extension(): IExtension { return this._extension; }
|
||||
set extension(extension: IExtension) { this._extension = extension; this.update(); }
|
||||
update(): void { this.render(); }
|
||||
abstract render(): void;
|
||||
}
|
||||
|
||||
export class Label extends ExtensionWidget {
|
||||
|
||||
constructor(
|
||||
private element: HTMLElement,
|
||||
private fn: (extension: IExtension) => string,
|
||||
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService
|
||||
) {
|
||||
super();
|
||||
this.render();
|
||||
}
|
||||
|
||||
render(): void {
|
||||
this.element.textContent = this.extension ? this.fn(this.extension) : '';
|
||||
}
|
||||
}
|
||||
|
||||
export class InstallCountWidget extends ExtensionWidget {
|
||||
|
||||
constructor(
|
||||
private container: HTMLElement,
|
||||
private small: boolean,
|
||||
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService
|
||||
) {
|
||||
super();
|
||||
addClass(container, 'extension-install-count');
|
||||
this.render();
|
||||
}
|
||||
|
||||
render(): void {
|
||||
this.container.innerHTML = '';
|
||||
|
||||
if (!this.extension) {
|
||||
return;
|
||||
}
|
||||
|
||||
const installCount = this.extension.installCount;
|
||||
|
||||
if (installCount === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let installLabel: string;
|
||||
|
||||
if (this.small) {
|
||||
if (installCount > 1000000) {
|
||||
installLabel = `${Math.floor(installCount / 100000) / 10}M`;
|
||||
} else if (installCount > 1000) {
|
||||
installLabel = `${Math.floor(installCount / 1000)}K`;
|
||||
} else {
|
||||
installLabel = String(installCount);
|
||||
}
|
||||
}
|
||||
else {
|
||||
installLabel = installCount.toLocaleString(platform.locale);
|
||||
}
|
||||
|
||||
append(this.container, $('span.octicon.octicon-cloud-download'));
|
||||
const count = append(this.container, $('span.count'));
|
||||
count.textContent = installLabel;
|
||||
}
|
||||
}
|
||||
|
||||
export class RatingsWidget extends ExtensionWidget {
|
||||
|
||||
constructor(
|
||||
private container: HTMLElement,
|
||||
private small: boolean
|
||||
) {
|
||||
super();
|
||||
addClass(container, 'extension-ratings');
|
||||
|
||||
if (this.small) {
|
||||
addClass(container, 'small');
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
render(): void {
|
||||
this.container.innerHTML = '';
|
||||
|
||||
if (!this.extension) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.extension.rating === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.small && !this.extension.ratingCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rating = Math.round(this.extension.rating * 2) / 2;
|
||||
|
||||
if (this.small) {
|
||||
append(this.container, $('span.full.star'));
|
||||
|
||||
const count = append(this.container, $('span.count'));
|
||||
count.textContent = String(rating);
|
||||
} else {
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
if (rating >= i) {
|
||||
append(this.container, $('span.full.star'));
|
||||
} else if (rating >= i - 0.5) {
|
||||
append(this.container, $('span.half.star'));
|
||||
} else {
|
||||
append(this.container, $('span.empty.star'));
|
||||
}
|
||||
}
|
||||
}
|
||||
this.container.title = this.extension.ratingCount === 1 ? localize('ratedBySingleUser', "Rated by 1 user")
|
||||
: typeof this.extension.ratingCount === 'number' && this.extension.ratingCount > 1 ? localize('ratedByUsers', "Rated by {0} users", this.extension.ratingCount) : localize('noRating', "No rating");
|
||||
}
|
||||
}
|
||||
|
||||
export class TooltipWidget extends ExtensionWidget {
|
||||
|
||||
constructor(
|
||||
private readonly parent: HTMLElement,
|
||||
private readonly disabledLabelAction: DisabledLabelAction,
|
||||
private readonly recommendationWidget: RecommendationWidget,
|
||||
private readonly reloadAction: ReloadAction,
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService
|
||||
) {
|
||||
super();
|
||||
this._register(Event.any<any>(
|
||||
this.disabledLabelAction.onDidChange,
|
||||
this.reloadAction.onDidChange,
|
||||
this.recommendationWidget.onDidChangeTooltip,
|
||||
this.labelService.onDidChangeFormatters
|
||||
)(() => this.render()));
|
||||
}
|
||||
|
||||
render(): void {
|
||||
this.parent.title = '';
|
||||
this.parent.removeAttribute('aria-label');
|
||||
this.parent.title = this.getTooltip();
|
||||
if (this.extension) {
|
||||
this.parent.setAttribute('aria-label', localize('extension-arialabel', "{0}. Press enter for extension details.", this.extension.displayName));
|
||||
}
|
||||
}
|
||||
|
||||
private getTooltip(): string {
|
||||
if (!this.extension) {
|
||||
return '';
|
||||
}
|
||||
if (this.reloadAction.enabled) {
|
||||
return this.reloadAction.tooltip;
|
||||
}
|
||||
if (this.disabledLabelAction.label) {
|
||||
return this.disabledLabelAction.label;
|
||||
}
|
||||
if (this.extension.local && this.extension.state === ExtensionState.Installed) {
|
||||
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return localize('extension enabled on remote', "Extension is enabled on '{0}'", this.labelService.getHostLabel(REMOTE_HOST_SCHEME, this.workbenchEnvironmentService.configuration.remoteAuthority));
|
||||
}
|
||||
return localize('extension enabled locally', "Extension is enabled locally.");
|
||||
}
|
||||
return this.recommendationWidget.tooltip;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class RecommendationWidget extends ExtensionWidget {
|
||||
|
||||
private element?: HTMLElement;
|
||||
private readonly disposables = this._register(new DisposableStore());
|
||||
|
||||
private _tooltip: string;
|
||||
get tooltip(): string { return this._tooltip; }
|
||||
set tooltip(tooltip: string) {
|
||||
if (this._tooltip !== tooltip) {
|
||||
this._tooltip = tooltip;
|
||||
this._onDidChangeTooltip.fire();
|
||||
}
|
||||
}
|
||||
private _onDidChangeTooltip: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChangeTooltip: Event<void> = this._onDidChangeTooltip.event;
|
||||
|
||||
constructor(
|
||||
private parent: HTMLElement,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IExtensionTipsService private readonly extensionTipsService: IExtensionTipsService
|
||||
) {
|
||||
super();
|
||||
this.render();
|
||||
this._register(toDisposable(() => this.clear()));
|
||||
this._register(this.extensionTipsService.onRecommendationChange(() => this.render()));
|
||||
}
|
||||
|
||||
private clear(): void {
|
||||
this.tooltip = '';
|
||||
this.parent.setAttribute('aria-label', this.extension ? localize('viewExtensionDetailsAria', "{0}. Press enter for extension details.", this.extension.displayName) : '');
|
||||
if (this.element) {
|
||||
this.parent.removeChild(this.element);
|
||||
}
|
||||
this.element = undefined;
|
||||
this.disposables.clear();
|
||||
}
|
||||
|
||||
render(): void {
|
||||
this.clear();
|
||||
if (!this.extension) {
|
||||
return;
|
||||
}
|
||||
const extRecommendations = this.extensionTipsService.getAllRecommendationsWithReason();
|
||||
if (extRecommendations[this.extension.identifier.id.toLowerCase()]) {
|
||||
this.element = append(this.parent, $('div.bookmark'));
|
||||
const recommendation = append(this.element, $('.recommendation'));
|
||||
append(recommendation, $('span.octicon.octicon-star'));
|
||||
const applyBookmarkStyle = (theme: ITheme) => {
|
||||
const bgColor = theme.getColor(extensionButtonProminentBackground);
|
||||
const fgColor = theme.getColor(extensionButtonProminentForeground);
|
||||
recommendation.style.borderTopColor = bgColor ? bgColor.toString() : 'transparent';
|
||||
recommendation.style.color = fgColor ? fgColor.toString() : 'white';
|
||||
};
|
||||
applyBookmarkStyle(this.themeService.getTheme());
|
||||
this.themeService.onThemeChange(applyBookmarkStyle, this, this.disposables);
|
||||
this.tooltip = extRecommendations[this.extension.identifier.id.toLowerCase()].reasonText;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class RemoteBadgeWidget extends ExtensionWidget {
|
||||
|
||||
private readonly remoteBadge = this._register(new MutableDisposable<RemoteBadge>());
|
||||
|
||||
private element: HTMLElement;
|
||||
|
||||
constructor(
|
||||
parent: HTMLElement,
|
||||
private readonly tooltip: boolean,
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
this.element = append(parent, $('.extension-remote-badge-container'));
|
||||
this.render();
|
||||
this._register(toDisposable(() => this.clear()));
|
||||
}
|
||||
|
||||
private clear(): void {
|
||||
if (this.remoteBadge.value) {
|
||||
this.element.removeChild(this.remoteBadge.value.element);
|
||||
}
|
||||
this.remoteBadge.clear();
|
||||
}
|
||||
|
||||
render(): void {
|
||||
this.clear();
|
||||
if (!this.extension || !this.extension.local || !this.extension.server) {
|
||||
return;
|
||||
}
|
||||
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
this.remoteBadge.value = this.instantiationService.createInstance(RemoteBadge, this.tooltip);
|
||||
append(this.element, this.remoteBadge.value.element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteBadge extends Disposable {
|
||||
|
||||
readonly element: HTMLElement;
|
||||
|
||||
constructor(
|
||||
private readonly tooltip: boolean,
|
||||
@ILabelService private readonly labelService: ILabelService,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
|
||||
) {
|
||||
super();
|
||||
this.element = $('div.extension-remote-badge');
|
||||
this.render();
|
||||
}
|
||||
|
||||
private render(): void {
|
||||
append(this.element, $('span.octicon.octicon-remote'));
|
||||
|
||||
const applyBadgeStyle = () => {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
const bgColor = this.themeService.getTheme().getColor(EXTENSION_BADGE_REMOTE_BACKGROUND);
|
||||
const fgColor = this.themeService.getTheme().getColor(EXTENSION_BADGE_REMOTE_FOREGROUND);
|
||||
this.element.style.backgroundColor = bgColor ? bgColor.toString() : '';
|
||||
this.element.style.color = fgColor ? fgColor.toString() : '';
|
||||
};
|
||||
applyBadgeStyle();
|
||||
this._register(this.themeService.onThemeChange(() => applyBadgeStyle()));
|
||||
|
||||
if (this.tooltip) {
|
||||
const updateTitle = () => {
|
||||
if (this.element) {
|
||||
this.element.title = localize('remote extension title', "Extension in {0}", this.labelService.getHostLabel(REMOTE_HOST_SCHEME, this.environmentService.configuration.remoteAuthority));
|
||||
}
|
||||
};
|
||||
this._register(this.labelService.onDidChangeFormatters(() => updateTitle()));
|
||||
updateTitle();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="#C5C5C5"/>
|
||||
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="#C5C5C5"/>
|
||||
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="#C5C5C5"/>
|
||||
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="#C5C5C5"/>
|
||||
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 484 B |
@@ -0,0 +1,7 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="white"/>
|
||||
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="white"/>
|
||||
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="white"/>
|
||||
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="white"/>
|
||||
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 474 B |
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.065 13H15v2H2.056v-2h5.009zm3.661-12H7.385L8.44 2.061 7.505 3H15V1h-4.274zM3.237 9H2.056v2H15V9H3.237zm4.208-4l.995 1-.995 1H15V5H7.445z" fill="#C5C5C5"/><path d="M5.072 4.03L7.032 6 5.978 7.061l-1.96-1.97-1.961 1.97L1 6l1.96-1.97L1 2.061 2.056 1l1.96 1.97L5.977 1l1.057 1.061L5.072 4.03z" fill="#F48771"/></svg>
|
||||
|
After Width: | Height: | Size: 419 B |
@@ -0,0 +1,7 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="#424242"/>
|
||||
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="#424242"/>
|
||||
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="#424242"/>
|
||||
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="#424242"/>
|
||||
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 484 B |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,122 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-action-bar .action-item .action-label.extension-action {
|
||||
padding: 0 5px;
|
||||
outline-offset: 2px;
|
||||
line-height: initial;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item .action-label.clear-extensions {
|
||||
background: url('clear-light.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-action-bar .action-item .action-label.clear-extensions {
|
||||
background: url('clear-dark.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .monaco-action-bar .action-item .action-label.clear-extensions {
|
||||
background: url('clear-hc.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.extension-editor-dropdown-action.dropdown:after {
|
||||
content: '▼';
|
||||
padding-left: 2px;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-action.ignore,
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-action.undo-ignore,
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-action.install:not(.installing),
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-action.uninstall:not(.uninstalling),
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-action.update,
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-action.theme,
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-action.extension-editor-dropdown-action,
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-action.reload,
|
||||
.monaco-action-bar .action-item.disabled .action-label.disable-status.hide,
|
||||
.monaco-action-bar .action-item.disabled .action-label.system-disable.hide,
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-status-label.hide,
|
||||
.monaco-action-bar .action-item.disabled .action-label.malicious-status.not-malicious {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-status-label:before {
|
||||
content: '✓';
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item .action-label.disable-status,
|
||||
.monaco-action-bar .action-item .action-label.malicious-status,
|
||||
.monaco-action-bar .action-item.disabled .action-label.extension-status-label {
|
||||
opacity: 0.9;
|
||||
line-height: initial;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item .action-label.disable-status,
|
||||
.monaco-action-bar .action-item .action-label.malicious-status {
|
||||
border-radius: 4px;
|
||||
color: inherit;
|
||||
background-color: transparent;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar > .actions-container > .action-item > .action-label.disable-status {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar > .actions-container > .action-item > .action-label.system-disable,
|
||||
.extensions-viewlet>.extensions .extension>.details>.footer>.monaco-action-bar .action-item .action-label.system-disable {
|
||||
margin: 0.15em;
|
||||
}
|
||||
|
||||
.monaco-action-bar .action-item .action-label.system-disable.icon {
|
||||
opacity: 1;
|
||||
height: 18px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.extension-status-label,
|
||||
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.disable-status,
|
||||
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.malicious-status {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.extension-status-label:hover,
|
||||
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.disable-status:hover,
|
||||
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.malicious-status:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.extensions-viewlet>.extensions .extension>.details>.footer>.monaco-action-bar .action-item .action-label.extension-action.manage.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.extensions-viewlet>.extensions .extension>.details>.footer>.monaco-action-bar .action-item .action-label.extension-action.manage {
|
||||
height: 18px;
|
||||
width: 10px;
|
||||
border: none;
|
||||
background: url('configure-light.svg') center center no-repeat;
|
||||
outline-offset: 0px;
|
||||
margin-top: 0.15em
|
||||
}
|
||||
|
||||
.vs-dark .extensions-viewlet>.extensions .extension>.details>.footer>.monaco-action-bar .action-item .action-label.extension-action.manage {
|
||||
background: url('configure-dark.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.hc-black .extensions-viewlet>.extensions .extension>.details>.footer>.monaco-action-bar .action-item .action-label.extension-action.manage {
|
||||
background: url('configure-hc.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.extension-editor > .header.recommended > .details > .recommendation > .monaco-action-bar .actions-container {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
@@ -0,0 +1,389 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.extension-editor {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.extension-editor .clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.extension-editor > .header {
|
||||
display: flex;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 14px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .icon-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .icon-container .icon {
|
||||
height: 128px;
|
||||
width: 128px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .icon-container .extension-remote-badge {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 88px;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
border-radius: 20px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .icon-container .extension-remote-badge .octicon {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details {
|
||||
padding-left: 20px;
|
||||
overflow: hidden;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .title > .name {
|
||||
flex: 0;
|
||||
font-size: 26px;
|
||||
line-height: 30px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .title > .identifier {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
opacity: 0.6;
|
||||
background: rgba(173, 173, 173, 0.31);
|
||||
padding: 0px 4px;
|
||||
border-radius: 4px;
|
||||
user-select: text;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .title > .builtin {
|
||||
font-size: 10px;
|
||||
font-style: italic;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.vs .extension-editor > .header > .details > .title > .preview {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .title > .preview {
|
||||
background: rgb(214, 63, 38);
|
||||
font-size: 10px;
|
||||
font-style: italic;
|
||||
margin-left: 10px;
|
||||
padding: 0px 4px;
|
||||
border-radius: 4px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtitle {
|
||||
padding-top: 6px;
|
||||
white-space: nowrap;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtitle > .publisher {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtitle > .install > .count {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtitle > span:not(:first-child):not(:empty),
|
||||
.extension-editor > .header > .details > .subtitle > a:not(:first-child):not(:empty) {
|
||||
border-left: 1px solid rgba(128, 128, 128, 0.7);
|
||||
margin-left: 14px;
|
||||
padding-left: 14px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .description {
|
||||
margin-top: 10px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar {
|
||||
text-align: initial;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar > .actions-container {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar > .actions-container > .action-item > .action-label {
|
||||
font-weight: 600;
|
||||
margin: 4px 8px 4px 0px;
|
||||
padding: 1px 6px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar > .actions-container > .action-item > .extension-action {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtext-container {
|
||||
display: block;
|
||||
float: left;
|
||||
margin-top: 0;
|
||||
font-size: 13px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtext-container > .monaco-action-bar {
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtext-container > .subtext {
|
||||
float:left;
|
||||
margin-top: 5px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.extension-editor > .header > .details > .subtext-container > .monaco-action-bar .action-label {
|
||||
margin-top: 4px;
|
||||
margin-left: 4px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.extension-editor > .body {
|
||||
height: calc(100% - 168px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .navbar {
|
||||
height: 36px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
line-height: 36px;
|
||||
padding-left: 20px;
|
||||
border-bottom: 1px solid rgba(136, 136, 136, 0.45);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container {
|
||||
justify-content: initial;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item > .action-label {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item > .action-label {
|
||||
font-size: inherit;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item > .action-label.checked {
|
||||
opacity: 1;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item > .action-label:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content {
|
||||
height: calc(100% - 36px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content.loading {
|
||||
background: url('loading.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content > .monaco-scrollable-element {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content > .nocontent {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content > .monaco-scrollable-element > .subcontent {
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
overflow-y: scroll;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content table {
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content details:not(:first-child) {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content details > summary {
|
||||
cursor: pointer;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
font-size: 120%;
|
||||
border-bottom: 1px solid rgba(128, 128, 128, 0.22);
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content details > summary:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content details > summary::-webkit-details-marker {
|
||||
color: rgba(128, 128, 128, 0.5);
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content table tr:nth-child(odd) {
|
||||
background-color: rgba(130, 130, 130, 0.04);
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content table tr:not(:first-child):hover {
|
||||
background-color: rgba(128, 128, 128, 0.15);
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content table th,
|
||||
.extension-editor > .body > .content table td {
|
||||
padding: 2px 16px 2px 4px;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content table th:last-child,
|
||||
.extension-editor > .body > .content table td:last-child {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content table th {
|
||||
text-align: left;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content table code:not(:empty) {
|
||||
font-family: var(--monaco-monospace-font);
|
||||
font-size: 90%;
|
||||
background-color: rgba(128, 128, 128, 0.17);
|
||||
border-radius: 4px;
|
||||
padding: 1px 4px;
|
||||
}
|
||||
|
||||
.extension-editor > .body > .content table .colorBox {
|
||||
box-sizing: border-box;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
display: inline-block;
|
||||
border-width: 0.1em;
|
||||
border-style: solid;
|
||||
border-color: rgb(0, 0, 0);
|
||||
margin: 0em 0.2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.vs-dark .extension-editor > .body > .content table .colorBox,
|
||||
.hc-black .extension-editor > .body > .content table .colorBox {
|
||||
border-color: rgb(238, 238, 238);
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .content .unknown-extension {
|
||||
line-height: 62px;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .content .unknown-extension > .error-marker {
|
||||
background-color: #BE1100;
|
||||
padding: 2px 4px;
|
||||
font-weight: bold;
|
||||
font-size: 11px;
|
||||
color: #CCC;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .unknown-extension > .message {
|
||||
padding-left: 10px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension > .details {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension > .details > .header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 19px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension > .icon {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension > .details > .header > .name {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension > .details > .header > .name:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension > .details > .header > .identifier {
|
||||
font-size: 90%;
|
||||
opacity: 0.6;
|
||||
margin-left: 10px;
|
||||
background: rgba(173, 173, 173, 0.31);
|
||||
padding: 0px 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension > .details > .footer {
|
||||
display: flex;
|
||||
line-height: 19px;
|
||||
overflow: hidden;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.extension-editor .subcontent .monaco-list-row .extension > .details > .footer > .author {
|
||||
font-size: 90%;
|
||||
font-weight: 600;
|
||||
opacity: 0.6;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5 1.5L15 0H22.5L24 1.5V9L22.5 10.5H15L13.5 9V1.5ZM15 1.5V9H22.5V1.5H15ZM0 15V6L1.5 4.5H9L10.5 6V13.5H18L19.5 15V22.5L18 24H10.5H9H1.5L0 22.5V15ZM9 13.5V6H1.5V13.5H9ZM9 15H1.5V22.5H9V15ZM10.5 22.5H18V15H10.5V22.5Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 385 B |
@@ -0,0 +1,13 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench .activitybar > .content .monaco-action-bar .action-label.extensions {
|
||||
-webkit-mask: url('extensions-activity-bar.svg') no-repeat 50% 50%;
|
||||
}
|
||||
|
||||
.extensions .split-view-view .panel-header .count-badge-wrapper {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.extensions-viewlet {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .header {
|
||||
height: 38px;
|
||||
box-sizing: border-box;
|
||||
padding: 5px 9px 5px 16px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .header > .search-box {
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
line-height: 18px;
|
||||
box-sizing: border-box;
|
||||
padding: 4px;
|
||||
border: 1px solid transparent;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions {
|
||||
height: calc(100% - 38px);
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .list-actionbar-container .monaco-action-bar .action-item > .octicon {
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .list-actionbar-container .monaco-action-bar .action-item.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extensions-list.hidden,
|
||||
.extensions-viewlet > .extensions .message-container.hidden {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .panel-header {
|
||||
padding-right: 28px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .panel-header > .title {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .message-container {
|
||||
padding: 5px 9px 5px 16px;
|
||||
cursor: default;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .message-container .message {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .monaco-list-row > .bookmark {
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .monaco-list-row > .bookmark > .recommendation {
|
||||
border-right: 20px solid transparent;
|
||||
border-top: 20px solid;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .monaco-list-row > .bookmark > .recommendation > .octicon {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 0 0 16px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension.loading {
|
||||
background: url('loading.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .monaco-list-row > .extension > .icon-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .icon-container > .icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
padding: 10px 14px 10px 0;
|
||||
flex-shrink: 0;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .monaco-list-row > .extension > .icon-container .extension-remote-badge {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .monaco-list-row > .extension > .details > .header-container > .header > .extension-remote-badge-container {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .monaco-list-row > .extension > .details > .header-container > .header .extension-remote-badge {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
border-radius: 20px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .monaco-list-row > .extension > .details > .header-container > .header .extension-remote-badge > .octicon {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.extensions-viewlet.narrow > .extensions .extension > .icon-container,
|
||||
.extensions-viewlet > .extensions .extension.loading > .icon-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details {
|
||||
flex: 1;
|
||||
padding: 4px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header-container {
|
||||
height: 19px;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header-container > .header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
flex-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header-container > .header > .name {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header-container > .header > .version {
|
||||
opacity: 0.85;
|
||||
font-size: 80%;
|
||||
padding-left: 6px;
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.extensions-viewlet:not(.narrow) > .extensions .extension > .details > .header-container > .header > .version {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header-container > .header > .install-count:not(:empty) {
|
||||
font-size: 80%;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header-container > .header > .install-count > .octicon {
|
||||
font-size: 100%;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .header-container > .header > .ratings {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.extensions-viewlet:not(.narrow) > .extensions .extension > .details > .header-container > .header > .extension-remote-badge-container,
|
||||
.extensions-viewlet.narrow > .extensions .extension > .details > .header-container > .header > .ratings,
|
||||
.extensions-viewlet.narrow > .extensions .extension > .details > .header-container > .header > .install-count {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .description {
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-right: 7px;
|
||||
height: 24px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .footer > .author {
|
||||
flex: 1;
|
||||
font-size: 90%;
|
||||
opacity: 0.9;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .selected .extension > .details > .footer > .author,
|
||||
.extensions-viewlet > .extensions .selected.focused .extension > .details > .footer > .author {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .footer > .monaco-action-bar > .actions-container {
|
||||
flex-wrap: wrap-reverse;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .footer > .monaco-action-bar > .actions-container .extension-action {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.extensions-viewlet.narrow > .extensions .extension > .details > .footer > .monaco-action-bar > .actions-container .extension-action {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .footer > .monaco-action-bar .action-label {
|
||||
margin-top: 0.3em;
|
||||
margin-left: 0.3em;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension > .details > .footer > .monaco-action-bar .action-label:not(:empty) {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .bookmark,
|
||||
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .bookmark,
|
||||
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension > .icon-container > .icon,
|
||||
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension > .icon-container > .icon,
|
||||
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension > .details > .header-container,
|
||||
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension > .details > .header-container,
|
||||
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension > .details > .description,
|
||||
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension > .details > .description,
|
||||
.vs .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension > .details > .footer > .author,
|
||||
.vs-dark .extensions-viewlet > .extensions .monaco-list-row.disabled > .extension > .details > .footer > .author {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.extensions-viewlet > .extensions .extension .ellipsis {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.extensions-badge.progress-badge > .badge-content {
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgdmlld0JveD0iMiAyIDE0IDE0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDIgMiAxNCAxNCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTkgMTZjLTMuODYgMC03LTMuMTQtNy03czMuMTQtNyA3LTdjMy44NTkgMCA3IDMuMTQxIDcgN3MtMy4xNDEgNy03IDd6bTAtMTIuNmMtMy4wODggMC01LjYgMi41MTMtNS42IDUuNnMyLjUxMiA1LjYgNS42IDUuNiA1LjYtMi41MTIgNS42LTUuNi0yLjUxMi01LjYtNS42LTUuNnptMy44NiA3LjFsLTMuMTYtMS44OTZ2LTMuODA0aC0xLjR2NC41OTZsMy44NCAyLjMwNS43Mi0xLjIwMXoiLz48L3N2Zz4=");
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.extension-ratings {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.extension-ratings.small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.extension-ratings > .star {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.extension-ratings > .star:not(:first-child) {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.extension-ratings.small > .star {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-image: url('star-small.svg');
|
||||
}
|
||||
|
||||
.extension-ratings > .full {
|
||||
background-image: url('star-full.svg');
|
||||
}
|
||||
|
||||
.extension-ratings > .half {
|
||||
background-image: url('star-half.svg');
|
||||
}
|
||||
|
||||
.extension-ratings > .empty {
|
||||
background-image: url('star-empty.svg');
|
||||
}
|
||||
|
||||
.extension-ratings > .count {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.extension-ratings.small > .count {
|
||||
margin-left: 2px;
|
||||
}
|
||||
1
src/vs/workbench/contrib/extensions/browser/media/language-icon.svg
Executable file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>Market_LanguageGeneric</title><path d="M14.315,11H1.685a6.912,6.912,0,0,1,0-6h12.63a6.912,6.912,0,0,1,0,6Z" fill="#fff"/><path d="M8,0a8,8,0,1,0,8,8A8.009,8.009,0,0,0,8,0ZM8,1a6.993,6.993,0,0,1,5.736,3H2.264A6.991,6.991,0,0,1,8,1ZM8,15a6.991,6.991,0,0,1-5.736-3H13.736A6.993,6.993,0,0,1,8,15Zm6.315-4H1.685a6.912,6.912,0,0,1,0-6h12.63a6.912,6.912,0,0,1,0,6Z" fill="#2b2b2b"/><path d="M8,1a6.993,6.993,0,0,1,5.736,3H2.264A6.991,6.991,0,0,1,8,1ZM8,15a6.991,6.991,0,0,1-5.736-3H13.736A6.993,6.993,0,0,1,8,15Z" fill="#ff8c00"/><path d="M8,0a8,8,0,1,0,8,8A8.009,8.009,0,0,0,8,0ZM8,1a6.993,6.993,0,0,1,5.736,3H2.264A6.991,6.991,0,0,1,8,1ZM8,15a6.991,6.991,0,0,1-5.736-3H13.736A6.993,6.993,0,0,1,8,15Zm6.315-4H1.685a6.912,6.912,0,0,1,0-6h12.63a6.912,6.912,0,0,1,0,6Z" fill="#2b2b2b"/><path d="M8,1a6.993,6.993,0,0,1,5.736,3H2.264A6.991,6.991,0,0,1,8,1ZM8,15a6.991,6.991,0,0,1-5.736-3H13.736A6.993,6.993,0,0,1,8,15Z" fill="#767676"/><path d="M5.783,6.783,4.565,8,5.783,9.217l-.566.566L3.435,8,5.217,6.217Zm5-.566-.566.566L11.435,8,10.217,9.217l.566.566L12.565,8Zm-4.14,3.6.714.358,2-4-.714-.358Z" fill="#2b2b2b"/></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,36 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
175
src/vs/workbench/contrib/extensions/browser/media/markdown.css
Normal file
@@ -0,0 +1,175 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
body {
|
||||
padding: 10px 20px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:focus,
|
||||
input:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 1px solid -webkit-focus-ring-color;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 2px;
|
||||
border-bottom: 2px solid;
|
||||
}
|
||||
|
||||
h1 {
|
||||
padding-bottom: 0.3em;
|
||||
line-height: 1.2;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table > thead > tr > th {
|
||||
text-align: left;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
table > thead > tr > th,
|
||||
table > thead > tr > td,
|
||||
table > tbody > tr > th,
|
||||
table > tbody > tr > td {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
table > tbody > tr + tr > td {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 7px 0 5px;
|
||||
padding: 0 16px 0 10px;
|
||||
border-left-width: 5px;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
}
|
||||
|
||||
.mac code {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
code > div {
|
||||
padding: 16px;
|
||||
border-radius: 3px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#scroll-to-top {
|
||||
position: fixed;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
right: 25px;
|
||||
bottom: 25px;
|
||||
background-color:#444444;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
box-shadow: 1px 1px 1px rgba(0,0,0,.25);
|
||||
outline: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#scroll-to-top:hover {
|
||||
background-color:#007acc;
|
||||
box-shadow: 2px 2px 2px rgba(0,0,0,.25);
|
||||
}
|
||||
|
||||
body.vscode-light #scroll-to-top {
|
||||
background-color: #949494;
|
||||
}
|
||||
|
||||
body.vscode-high-contrast #scroll-to-top:hover {
|
||||
background-color: #007acc;
|
||||
}
|
||||
|
||||
body.vscode-high-contrast #scroll-to-top {
|
||||
background-color: black;
|
||||
border: 2px solid #6fc3df;
|
||||
box-shadow: none;
|
||||
}
|
||||
body.vscode-high-contrast #scroll-to-top:hover {
|
||||
background-color: #007acc;
|
||||
}
|
||||
|
||||
#scroll-to-top span.icon::before {
|
||||
content: "";
|
||||
display: block;
|
||||
/* Chevron up icon */
|
||||
background:url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjIuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxNiAxNiIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMTYgMTY7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCS5zdDB7ZmlsbDojRkZGRkZGO30KCS5zdDF7ZmlsbDpub25lO30KPC9zdHlsZT4KPHRpdGxlPnVwY2hldnJvbjwvdGl0bGU+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik04LDUuMWwtNy4zLDcuM0wwLDExLjZsOC04bDgsOGwtMC43LDAuN0w4LDUuMXoiLz4KPHJlY3QgY2xhc3M9InN0MSIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+Cjwvc3ZnPgo=');
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/** Theming */
|
||||
.vscode-light code > div {
|
||||
background-color: rgba(220, 220, 220, 0.4);
|
||||
}
|
||||
|
||||
.vscode-dark code > div {
|
||||
background-color: rgba(10, 10, 10, 0.4);
|
||||
}
|
||||
|
||||
.vscode-high-contrast code > div {
|
||||
background-color: rgb(0, 0, 0);
|
||||
}
|
||||
|
||||
.vscode-high-contrast h1 {
|
||||
border-color: rgb(0, 0, 0);
|
||||
}
|
||||
|
||||
.vscode-light table > thead > tr > th {
|
||||
border-color: rgba(0, 0, 0, 0.69);
|
||||
}
|
||||
|
||||
.vscode-dark table > thead > tr > th {
|
||||
border-color: rgba(255, 255, 255, 0.69);
|
||||
}
|
||||
|
||||
.vscode-light h1,
|
||||
.vscode-light hr,
|
||||
.vscode-light table > tbody > tr + tr > td {
|
||||
border-color: rgba(0, 0, 0, 0.18);
|
||||
}
|
||||
|
||||
.vscode-dark h1,
|
||||
.vscode-dark hr,
|
||||
.vscode-dark table > tbody > tr + tr > td {
|
||||
border-color: rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM11.9139 8C11.9139 10.1616 10.1616 11.9139 8 11.9139C5.83839 11.9139 4.08606 10.1616 4.08606 8C4.08606 5.83839 5.83839 4.08606 8 4.08606C10.1616 4.08606 11.9139 5.83839 11.9139 8ZM8 3.86919C10.2814 3.86919 12.1308 5.71862 12.1308 8C12.1308 8.00001 12.1308 8 12.1308 8C12.1308 5.71862 10.2814 3.86919 8 3.86919Z" fill="#848484"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 715 B |
@@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM11.9139 8C11.9139 10.1616 10.1616 11.9139 8 11.9139C5.83839 11.9139 4.08606 10.1616 4.08606 8C4.08606 5.83839 5.83839 4.08606 8 4.08606C10.1616 4.08606 11.9139 5.83839 11.9139 8ZM8 3.86919C10.2814 3.86919 12.1308 5.71862 12.1308 8C12.1308 8.00001 12.1308 8 12.1308 8C12.1308 5.71862 10.2814 3.86919 8 3.86919Z" fill="#848484"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 715 B |
@@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M8 2C8.55078 2 9.08203 2.07227 9.59375 2.2168C10.1055 2.35742 10.582 2.55859 11.0234 2.82031C11.4688 3.08203 11.873 3.39648 12.2363 3.76367C12.6035 4.12695 12.918 4.53125 13.1797 4.97656C13.4414 5.41797 13.6426 5.89453 13.7832 6.40625C13.9277 6.91797 14 7.44922 14 8C14 8.55078 13.9277 9.08203 13.7832 9.59375C13.6426 10.1055 13.4414 10.584 13.1797 11.0293C12.918 11.4707 12.6035 11.875 12.2363 12.2422C11.873 12.6055 11.4688 12.918 11.0234 13.1797C10.582 13.4414 10.1055 13.6445 9.59375 13.7891C9.08203 13.9297 8.55078 14 8 14C7.44922 14 6.91797 13.9297 6.40625 13.7891C5.89453 13.6445 5.41602 13.4414 4.9707 13.1797C4.5293 12.918 4.125 12.6055 3.75781 12.2422C3.39453 11.875 3.08203 11.4707 2.82031 11.0293C2.55859 10.584 2.35547 10.1055 2.21094 9.59375C2.07031 9.08203 2 8.55078 2 8C2 7.44922 2.07031 6.91797 2.21094 6.40625C2.35547 5.89453 2.55859 5.41797 2.82031 4.97656C3.08203 4.53125 3.39453 4.12695 3.75781 3.76367C4.125 3.39648 4.5293 3.08203 4.9707 2.82031C5.41602 2.55859 5.89453 2.35742 6.40625 2.2168C6.91797 2.07227 7.44922 2 8 2Z" fill="#F48771"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M8 2C8.55078 2 9.08203 2.07227 9.59375 2.2168C10.1055 2.35742 10.582 2.55859 11.0234 2.82031C11.4688 3.08203 11.873 3.39648 12.2363 3.76367C12.6035 4.12695 12.918 4.53125 13.1797 4.97656C13.4414 5.41797 13.6426 5.89453 13.7832 6.40625C13.9277 6.91797 14 7.44922 14 8C14 8.55078 13.9277 9.08203 13.7832 9.59375C13.6426 10.1055 13.4414 10.584 13.1797 11.0293C12.918 11.4707 12.6035 11.875 12.2363 12.2422C11.873 12.6055 11.4688 12.918 11.0234 13.1797C10.582 13.4414 10.1055 13.6445 9.59375 13.7891C9.08203 13.9297 8.55078 14 8 14C7.44922 14 6.91797 13.9297 6.40625 13.7891C5.89453 13.6445 5.41602 13.4414 4.9707 13.1797C4.5293 12.918 4.125 12.6055 3.75781 12.2422C3.39453 11.875 3.08203 11.4707 2.82031 11.0293C2.55859 10.584 2.35547 10.1055 2.21094 9.59375C2.07031 9.08203 2 8.55078 2 8C2 7.44922 2.07031 6.91797 2.21094 6.40625C2.35547 5.89453 2.55859 5.41797 2.82031 4.97656C3.08203 4.53125 3.39453 4.12695 3.75781 3.76367C4.125 3.39648 4.5293 3.08203 4.9707 2.82031C5.41602 2.55859 5.89453 2.35742 6.40625 2.2168C6.91797 2.07227 7.44922 2 8 2Z" fill="#A1260D"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3V11.5L14.5 12H12V14.5L11.5 15H1.5L1 14.5V4.5L1.5 4H3.985V1.5L4.485 1H13L13.353 1.147L14.853 2.647L15 3ZM12 6V11H14V3.206L12.793 2H4.985V4H10L10.353 4.146L11.853 5.646L12 6ZM11 14H2V5H3V8.07143H9V5H9.793L11 6.208V14ZM8 5H6V7.5H8V5Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 406 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3V11.5L14.5 12H12V14.5L11.5 15H1.5L1 14.5V4.5L1.5 4H3.985V1.5L4.485 1H13L13.353 1.147L14.853 2.647L15 3ZM12 6V11H14V3.206L12.793 2H4.985V4H10L10.353 4.146L11.853 5.646L12 6ZM11 14H2V5H3V8.07143H9V5H9.793L11 6.208V14ZM8 5H6V7.5H8V5Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 406 B |
@@ -0,0 +1,5 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g opacity="0.5">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.59454 6.25211L8 1L6.40546 6.25211H1L5.37311 9.65247L3.7496 15L8 11.695L12.2504 15L10.6269 9.65247L15 6.25211H9.59454ZM2.34804 6.72168H6.72044L8 2.50706L8.00002 2.50708L6.72046 6.7217H2.34805L2.34804 6.72168ZM5.88539 9.4722L4.57848 13.7769L4.57851 13.7769L5.8854 9.47221L5.88539 9.4722ZM13.6519 6.7217L13.652 6.72168H9.27956L9.27958 6.7217H13.6519ZM4.90113 7.6229H7.26847L8.00002 5.21332L8.73156 7.6229H11.0989L9.18369 9.1121L9.91523 11.5217L8.00002 10.0325L6.0848 11.5217L6.81635 9.1121L4.90113 7.6229Z" fill="#C5C5C5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 699 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.59454 6.25211L8 1L6.40546 6.25211H1L5.37311 9.65247L3.7496 15L8 11.695L12.2504 15L10.6269 9.65247L15 6.25211H9.59454Z" fill="#FF8E00"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 291 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.40546 6.25211L8 1L9.59454 6.25211H15L10.6269 9.65247L12.2504 15L8 11.695L3.7496 15L5.37311 9.65247L1 6.25211H6.40546ZM8 10.0325L8.00002 10.0325L9.91523 11.5217L9.18369 9.1121L11.0989 7.6229H8.73156L8.00002 5.21332L8 5.21338V10.0325V10.0325ZM8 2.50714L8.00002 2.50708L8 2.50706V2.50714ZM13.6519 6.7217L13.652 6.72168H9.27956L9.27958 6.7217H13.6519Z" fill="#FF8E00"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 521 B |
@@ -0,0 +1,10 @@
|
||||
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.99659 3.90757L5 0.625L4.00341 3.90757H0.625L3.35819 6.0328L2.3435 9.375L5 7.3094L7.6565 9.375L6.64181 6.0328L9.375 3.90757H5.99659Z" fill="#FF8E00"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="10" height="10" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 431 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.99977 14V2.18091L12.9998 8.06215L3.99977 14ZM5.5 4.99997L10.3145 8.06215L5.5 11.1809L5.5 4.99997Z" fill="#89D185"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 271 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.99977 14V2.18091L12.9998 8.06215L3.99977 14ZM5.5 4.99997L10.3145 8.06215L5.5 11.1809L5.5 4.99997Z" fill="#388A34"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 271 B |
BIN
src/vs/workbench/contrib/extensions/browser/media/theme-icon.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |