mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
fine tune hover and extension status
This commit is contained in:
parent
2feb2fc6b5
commit
5d8d47ff3a
|
@ -13,7 +13,7 @@ import { Cache, CacheResult } from 'vs/base/common/cache';
|
|||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { getErrorMessage, isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { dispose, toDisposable, Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { append, $, finalHandler, join, hide, show, addDisposableListener, EventType, setParentFlowTo, reset } from 'vs/base/browser/dom';
|
||||
import { append, $, finalHandler, join, addDisposableListener, EventType, setParentFlowTo, reset } from 'vs/base/browser/dom';
|
||||
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
@ -28,7 +28,7 @@ import { IEditorOpenContext } from 'vs/workbench/common/editor';
|
|||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import {
|
||||
UpdateAction, ReloadAction, EnableDropDownAction, DisableDropDownAction, ExtensionStatusLabelAction, SetFileIconThemeAction, SetColorThemeAction,
|
||||
RemoteInstallAction, ExtensionToolTipAction, ExtensionStatusAction, LocalInstallAction, ToggleSyncExtensionAction, SetProductIconThemeAction,
|
||||
RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ToggleSyncExtensionAction, SetProductIconThemeAction,
|
||||
ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, UninstallAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction,
|
||||
InstallAnotherVersionAction, ExtensionEditorManageExtensionAction, WebInstallAction
|
||||
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
|
@ -49,7 +49,7 @@ import { KeybindingParser } from 'vs/base/common/keybindingParser';
|
|||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { getDefaultValue } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { isUndefined } from 'vs/base/common/types';
|
||||
import { isString, isUndefined } from 'vs/base/common/types';
|
||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { IWebviewService, Webview, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
|
@ -70,7 +70,8 @@ import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
|
|||
import { attachKeybindingLabelStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { errorIcon, infoIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
|
||||
import { errorIcon, infoIcon, starEmptyIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
|
||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
|
||||
class NavBar extends Disposable {
|
||||
|
||||
|
@ -140,11 +141,10 @@ interface IExtensionEditorTemplate {
|
|||
rating: HTMLElement;
|
||||
description: HTMLElement;
|
||||
extensionActionBar: ActionBar;
|
||||
status: HTMLElement;
|
||||
recommendation: HTMLElement;
|
||||
navbar: NavBar;
|
||||
content: HTMLElement;
|
||||
subtextContainer: HTMLElement;
|
||||
subtext: HTMLElement;
|
||||
ignoreActionbar: ActionBar;
|
||||
header: HTMLElement;
|
||||
}
|
||||
|
||||
|
@ -227,8 +227,8 @@ export class ExtensionEditor extends EditorPane {
|
|||
|
||||
const description = append(details, $('.description'));
|
||||
|
||||
const extensionActions = append(details, $('.actions'));
|
||||
const extensionActionBar = this._register(new ActionBar(extensionActions, {
|
||||
const extensionActionsContainer = append(details, $('.actions'));
|
||||
const extensionActionBar = this._register(new ActionBar(extensionActionsContainer, {
|
||||
animated: false,
|
||||
actionViewItemProvider: (action: IAction) => {
|
||||
if (action instanceof ExtensionDropDownAction) {
|
||||
|
@ -242,20 +242,14 @@ export class ExtensionEditor extends EditorPane {
|
|||
focusOnlyEnabledItems: true
|
||||
}));
|
||||
|
||||
const subtextContainer = append(details, $('.subtext-container'));
|
||||
const subtext = append(subtextContainer, $('.subtext'));
|
||||
const ignoreActionbar = this._register(new ActionBar(subtextContainer, { animated: false }));
|
||||
const status = append(extensionActionsContainer, $('.status'));
|
||||
const recommendation = append(details, $('.recommendation'));
|
||||
|
||||
this._register(Event.chain(extensionActionBar.onDidRun)
|
||||
.map(({ error }) => error)
|
||||
.filter(error => !!error)
|
||||
.on(this.onError, this));
|
||||
|
||||
this._register(Event.chain(ignoreActionbar.onDidRun)
|
||||
.map(({ error }) => error)
|
||||
.filter(error => !!error)
|
||||
.on(this.onError, this));
|
||||
|
||||
const body = append(root, $('.body'));
|
||||
const navbar = new NavBar(body);
|
||||
|
||||
|
@ -266,20 +260,19 @@ export class ExtensionEditor extends EditorPane {
|
|||
builtin,
|
||||
content,
|
||||
description,
|
||||
extensionActionBar,
|
||||
header,
|
||||
icon,
|
||||
iconContainer,
|
||||
version,
|
||||
ignoreActionbar,
|
||||
installCount,
|
||||
name,
|
||||
navbar,
|
||||
preview,
|
||||
publisher,
|
||||
rating,
|
||||
subtext,
|
||||
subtextContainer
|
||||
extensionActionBar,
|
||||
status,
|
||||
recommendation
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -381,7 +374,6 @@ export class ExtensionEditor extends EditorPane {
|
|||
];
|
||||
const reloadAction = this.instantiationService.createInstance(ReloadAction);
|
||||
const combinedInstallAction = this.instantiationService.createInstance(InstallDropdownAction);
|
||||
const systemDisabledWarningAction = this.instantiationService.createInstance(ExtensionStatusAction);
|
||||
const actions = [
|
||||
reloadAction,
|
||||
this.instantiationService.createInstance(ExtensionStatusLabelAction),
|
||||
|
@ -403,10 +395,9 @@ export class ExtensionEditor extends EditorPane {
|
|||
]),
|
||||
this.instantiationService.createInstance(ToggleSyncExtensionAction),
|
||||
this.instantiationService.createInstance(ExtensionEditorManageExtensionAction),
|
||||
systemDisabledWarningAction,
|
||||
this.instantiationService.createInstance(ExtensionToolTipAction, systemDisabledWarningAction, reloadAction),
|
||||
];
|
||||
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets]);
|
||||
const extensionStatus = this.instantiationService.createInstance(ExtensionStatusAction);
|
||||
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets, extensionStatus]);
|
||||
extensionContainers.extension = extension;
|
||||
|
||||
template.extensionActionBar.clear();
|
||||
|
@ -416,7 +407,9 @@ export class ExtensionEditor extends EditorPane {
|
|||
this.transientDisposables.add(disposable);
|
||||
}
|
||||
|
||||
this.setSubText(extension, template);
|
||||
this.setStatus(extensionStatus, template);
|
||||
this.setRecommendationText(extension, template);
|
||||
|
||||
template.content.innerText = ''; // Clear content before setting navbar actions.
|
||||
|
||||
template.navbar.clear();
|
||||
|
@ -462,24 +455,40 @@ export class ExtensionEditor extends EditorPane {
|
|||
this.editorLoadComplete = true;
|
||||
}
|
||||
|
||||
private setSubText(extension: IExtension, template: IExtensionEditorTemplate): void {
|
||||
hide(template.subtextContainer);
|
||||
|
||||
const updateRecommendationFn = () => {
|
||||
const extRecommendations = this.extensionRecommendationsService.getAllRecommendationsWithReason();
|
||||
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
|
||||
template.subtext.textContent = extRecommendations[extension.identifier.id.toLowerCase()].reasonText;
|
||||
show(template.subtextContainer);
|
||||
} else if (this.extensionIgnoredRecommendationsService.globalIgnoredRecommendations.indexOf(extension.identifier.id.toLowerCase()) !== -1) {
|
||||
template.subtext.textContent = localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension.");
|
||||
show(template.subtextContainer);
|
||||
} else {
|
||||
template.subtext.textContent = '';
|
||||
hide(template.subtextContainer);
|
||||
private setStatus(extensionStatus: ExtensionStatusAction, template: IExtensionEditorTemplate): void {
|
||||
const updateStatus = () => {
|
||||
reset(template.status);
|
||||
const status = extensionStatus.status;
|
||||
if (status) {
|
||||
const markdown = new MarkdownString('', { isTrusted: true, supportThemeIcons: true });
|
||||
if (status.icon) {
|
||||
markdown.appendMarkdown(`$(${status.icon.id}) `);
|
||||
}
|
||||
if (isString(status.message)) {
|
||||
markdown.appendText(status.message);
|
||||
} else {
|
||||
markdown.appendMarkdown(status.message.value);
|
||||
}
|
||||
append(template.status, renderMarkdown(markdown));
|
||||
}
|
||||
};
|
||||
updateRecommendationFn();
|
||||
this.transientDisposables.add(this.extensionRecommendationsService.onDidChangeRecommendations(() => updateRecommendationFn()));
|
||||
updateStatus();
|
||||
this.transientDisposables.add(extensionStatus.onDidChangeStatus(() => updateStatus()));
|
||||
}
|
||||
|
||||
private setRecommendationText(extension: IExtension, template: IExtensionEditorTemplate): void {
|
||||
const updateRecommendationText = () => {
|
||||
reset(template.recommendation);
|
||||
const extRecommendations = this.extensionRecommendationsService.getAllRecommendationsWithReason();
|
||||
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
|
||||
append(template.recommendation, $(`span${ThemeIcon.asCSSSelector(starEmptyIcon)}`));
|
||||
append(template.recommendation, $(`span.recommendation-text`, undefined, extRecommendations[extension.identifier.id.toLowerCase()].reasonText));
|
||||
} else if (this.extensionIgnoredRecommendationsService.globalIgnoredRecommendations.indexOf(extension.identifier.id.toLowerCase()) !== -1) {
|
||||
append(template.recommendation, $(`span.recommendation-text`, undefined, localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension.")));
|
||||
}
|
||||
};
|
||||
updateRecommendationText();
|
||||
this.transientDisposables.add(this.extensionRecommendationsService.onDidChangeRecommendations(() => updateRecommendationText()));
|
||||
}
|
||||
|
||||
override clearInput(): void {
|
||||
|
@ -1615,12 +1624,16 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
|||
const link = theme.getColor(textLinkForeground);
|
||||
if (link) {
|
||||
collector.addRule(`.monaco-workbench .extension-editor .content a { color: ${link}; }`);
|
||||
collector.addRule(`.monaco-workbench .extension-editor > .header > .details > .actions > .status a { color: ${link}; }`);
|
||||
}
|
||||
|
||||
const activeLink = theme.getColor(textLinkActiveForeground);
|
||||
if (activeLink) {
|
||||
collector.addRule(`.monaco-workbench .extension-editor .content a:hover,
|
||||
.monaco-workbench .extension-editor .content a:active { color: ${activeLink}; }`);
|
||||
collector.addRule(`.monaco-workbench .extension-editor > .header > .details > .actions > .status a:hover,
|
||||
.monaco-workbench .extension-editor > .header > .details > .actions > .status a:active { color: ${activeLink}; }`);
|
||||
|
||||
}
|
||||
|
||||
const buttonHoverBackgroundColor = theme.getColor(buttonHoverBackground);
|
||||
|
|
|
@ -8,7 +8,7 @@ import { localize } from 'vs/nls';
|
|||
import { IAction, Action, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { Delayer, Promises } from 'vs/base/common/async';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import * as json from 'vs/base/common/json';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
|
@ -62,6 +62,7 @@ import { isIOS, isWeb } from 'vs/base/common/platform';
|
|||
import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService';
|
||||
import { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { isVirtualWorkspace } from 'vs/platform/remote/common/remoteHosts';
|
||||
import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent';
|
||||
|
||||
function getRelativeDateLabel(date: Date): string {
|
||||
const delta = new Date().getTime() - date.getTime();
|
||||
|
@ -1957,82 +1958,7 @@ export class ToggleSyncExtensionAction extends ExtensionDropDownAction {
|
|||
}
|
||||
}
|
||||
|
||||
export class ExtensionToolTipAction extends ExtensionAction {
|
||||
|
||||
private static readonly Class = `${ExtensionAction.TEXT_ACTION_CLASS} disable-status`;
|
||||
|
||||
updateWhenCounterExtensionChanges: boolean = true;
|
||||
private _runningExtensions: IExtensionDescription[] | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly extensionStatusIconAction: ExtensionStatusAction,
|
||||
private readonly reloadAction: ReloadAction,
|
||||
@IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService
|
||||
) {
|
||||
super('extensions.tooltip', extensionStatusIconAction.statusMessage, `${ExtensionToolTipAction.Class} hide`, false);
|
||||
this._register(extensionStatusIconAction.onDidChange(() => this.update(), this));
|
||||
this._register(this.extensionService.onDidChangeExtensions(this.updateRunningExtensions, this));
|
||||
this.updateRunningExtensions();
|
||||
}
|
||||
|
||||
private updateRunningExtensions(): void {
|
||||
this.extensionService.getExtensions().then(runningExtensions => { this._runningExtensions = runningExtensions; this.update(); });
|
||||
}
|
||||
|
||||
update(): void {
|
||||
this.label = this.getTooltip();
|
||||
this.class = ExtensionToolTipAction.Class;
|
||||
if (!this.label) {
|
||||
this.class = `${ExtensionToolTipAction.Class} hide`;
|
||||
}
|
||||
}
|
||||
|
||||
private getTooltip(): string {
|
||||
if (!this.extension) {
|
||||
return '';
|
||||
}
|
||||
if (this.reloadAction.enabled) {
|
||||
return this.reloadAction.tooltip;
|
||||
}
|
||||
if (this.extensionStatusIconAction.statusMessage) {
|
||||
return this.extensionStatusIconAction.statusMessage;
|
||||
}
|
||||
if (this.extension && this.extension.local && this.extension.state === ExtensionState.Installed && this._runningExtensions) {
|
||||
const isRunning = this._runningExtensions.some(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension!.identifier));
|
||||
const isEnabled = this.extensionEnablementService.isEnabled(this.extension.local);
|
||||
|
||||
if (isEnabled && isRunning) {
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
return localize('extension enabled on remote', "Extension is enabled on '{0}'", this.extension.server.label);
|
||||
}
|
||||
}
|
||||
if (this.extension.enablementState === EnablementState.EnabledGlobally) {
|
||||
return localize('globally enabled', "This extension is enabled globally.");
|
||||
}
|
||||
if (this.extension.enablementState === EnablementState.EnabledWorkspace) {
|
||||
return localize('workspace enabled', "This extension is enabled for this workspace by the user.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEnabled && !isRunning) {
|
||||
if (this.extension.enablementState === EnablementState.DisabledGlobally) {
|
||||
return localize('globally disabled', "This extension is disabled globally by the user.");
|
||||
}
|
||||
if (this.extension.enablementState === EnablementState.DisabledWorkspace) {
|
||||
return localize('workspace disabled', "This extension is disabled for this workspace by the user.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
override run(): Promise<any> {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
export type ExtensionStatus = { readonly message: IMarkdownString | string, readonly icon?: ThemeIcon };
|
||||
|
||||
export class ExtensionStatusAction extends ExtensionAction {
|
||||
|
||||
|
@ -2041,11 +1967,11 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
updateWhenCounterExtensionChanges: boolean = true;
|
||||
private _runningExtensions: IExtensionDescription[] | null = null;
|
||||
|
||||
private _statusIcon: ThemeIcon | undefined;
|
||||
get statusIcon(): ThemeIcon | undefined { return this._statusIcon; }
|
||||
private _status: ExtensionStatus | undefined;
|
||||
get status(): ExtensionStatus | undefined { return this._status; }
|
||||
|
||||
private _statusMessage: string | undefined;
|
||||
get statusMessage(): string | undefined { return this._statusMessage; }
|
||||
private readonly _onDidChangeStatus = this._register(new Emitter<void>());
|
||||
readonly onDidChangeStatus = this._onDidChangeStatus.event;
|
||||
|
||||
constructor(
|
||||
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
|
@ -2060,7 +1986,7 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
@IProductService private readonly productService: IProductService,
|
||||
@IWorkbenchExtensionEnablementService private readonly workbenchExtensionEnablementService: IWorkbenchExtensionEnablementService,
|
||||
) {
|
||||
super('extensions.install', '', `${ExtensionStatusAction.CLASS} hide`, false);
|
||||
super('extensions.status', '', `${ExtensionStatusAction.CLASS} hide`, false);
|
||||
this._register(this.labelService.onDidChangeFormatters(() => this.update(), this));
|
||||
this._register(this.extensionService.onDidChangeExtensions(this.updateRunningExtensions, this));
|
||||
this.updateRunningExtensions();
|
||||
|
@ -2072,9 +1998,7 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
}
|
||||
|
||||
update(): void {
|
||||
this.class = `${ExtensionStatusAction.CLASS} hide`;
|
||||
this._statusIcon = undefined;
|
||||
this.updateStatusMessage('');
|
||||
this.updateStatus(undefined, true);
|
||||
this.enabled = false;
|
||||
|
||||
if (!this.extension) {
|
||||
|
@ -2083,20 +2007,20 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
|
||||
if (this.extension.state === ExtensionState.Uninstalled && !this.extensionsWorkbenchService.canInstall(this.extension) && this.extension.gallery) {
|
||||
if (this.extension.isMalicious) {
|
||||
this.updateStatusIcon(warningIcon);
|
||||
this.updateStatusMessage(localize('malicious tooltip', "This extension was reported to be problematic."));
|
||||
this.updateStatus({ icon: warningIcon, message: localize('malicious tooltip', "This extension was reported to be problematic.") }, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.extensionManagementServerService.webExtensionManagementServer && !this.extensionManagementServerService.localExtensionManagementServer
|
||||
&& !this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
const productName = isWeb ? localize({ key: 'vscode web', comment: ['VS Code Web is the name of the product'] }, "VS Code Web") : this.productService.nameLong;
|
||||
this.updateStatusIcon(infoIcon);
|
||||
let message;
|
||||
if (this.extension.gallery.webExtension) {
|
||||
this.updateStatusMessage(localize('user disabled', "You have configured the '{0}' extension to be disabled in {1}. To enable it, please open user settings and remove it from `remote.extensionKind` setting.", this.extension.displayName || this.extension.identifier.id, productName));
|
||||
message = localize('user disabled', "You have configured the '{0}' extension to be disabled in {1}. To enable it, please open user settings and remove it from `remote.extensionKind` setting.", this.extension.displayName || this.extension.identifier.id, productName);
|
||||
} else {
|
||||
this.updateStatusMessage(localize('not web tooltip', "The '{0}' extension is not available in {1}.", this.extension.displayName || this.extension.identifier.id, productName));
|
||||
message = new MarkdownString(`${localize('not web tooltip', "The '{0}' extension is not available in {1}. Click {2} to learn more.", this.extension.displayName || this.extension.identifier.id, productName, `[${localize('more info', "More Information")}](https://aka.ms/vscode-remote-codespaces#_why-is-an-extension-not-installable-in-the-browser)`)}`);
|
||||
}
|
||||
this.updateStatus({ icon: infoIcon, message }, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2111,21 +2035,20 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
|
||||
// Extension is disabled by environment
|
||||
if (this.extension.enablementState === EnablementState.DisabledByEnvironment) {
|
||||
this.updateStatusMessage(localize('disabled by environment', "This extension is disabled by the environment."));
|
||||
this.updateStatus({ message: localize('disabled by environment', "This extension is disabled by the environment.") }, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Extension is enabled by environment
|
||||
if (this.extension.enablementState === EnablementState.EnabledByEnvironment) {
|
||||
this.updateStatusMessage(localize('enabled by environment', "This extension is enabled because it is required in the current environment."));
|
||||
this.updateStatus({ message: localize('enabled by environment', "This extension is enabled because it is required in the current environment.") }, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Extension is disabled by virtual workspace
|
||||
if (this.extension.enablementState === EnablementState.DisabledByVirtualWorkspace) {
|
||||
const details = getWorkspaceSupportTypeMessage(this.extension.local.manifest.capabilities?.virtualWorkspaces);
|
||||
this.updateStatusIcon(infoIcon);
|
||||
this.updateStatusMessage(details || localize('disabled because of virtual workspace', "This extension has been disabled because it does not support virtual workspaces."));
|
||||
this.updateStatus({ icon: infoIcon, message: details || localize('disabled because of virtual workspace', "This extension has been disabled because it does not support virtual workspaces.") }, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2134,8 +2057,7 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
const virtualSupportType = this.extensionManifestPropertiesService.getExtensionVirtualWorkspaceSupportType(this.extension.local.manifest);
|
||||
const details = getWorkspaceSupportTypeMessage(this.extension.local.manifest.capabilities?.virtualWorkspaces);
|
||||
if (virtualSupportType === 'limited' || details) {
|
||||
this.updateStatusIcon(infoIcon);
|
||||
this.updateStatusMessage(details || localize('extension limited because of virtual workspace', "This extension has limited features because the current workspace is virtual."));
|
||||
this.updateStatus({ icon: infoIcon, message: details || localize('extension limited because of virtual workspace', "This extension has limited features because the current workspace is virtual.") }, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2145,9 +2067,8 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
// All disabled dependencies of the extension are disabled by untrusted workspace
|
||||
(this.extension.enablementState === EnablementState.DisabledByExtensionDependency && this.workbenchExtensionEnablementService.getDependenciesEnablementStates(this.extension.local).every(([, enablementState]) => this.workbenchExtensionEnablementService.isEnabledEnablementState(enablementState) || enablementState === EnablementState.DisabledByTrustRequirement))) {
|
||||
this.enabled = true;
|
||||
this.updateStatusIcon(trustIcon);
|
||||
const untrustedDetails = getWorkspaceSupportTypeMessage(this.extension.local.manifest.capabilities?.untrustedWorkspaces);
|
||||
this.updateStatusMessage(untrustedDetails || localize('extension disabled because of trust requirement', "This extension has been disabled because the current workspace is not trusted."));
|
||||
this.updateStatus({ icon: trustIcon, message: untrustedDetails || localize('extension disabled because of trust requirement', "This extension has been disabled because the current workspace is not trusted.") }, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2157,8 +2078,7 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
const untrustedDetails = getWorkspaceSupportTypeMessage(this.extension.local.manifest.capabilities?.untrustedWorkspaces);
|
||||
if (untrustedSupportType === 'limited' || untrustedDetails) {
|
||||
this.enabled = true;
|
||||
this.updateStatusIcon(trustIcon);
|
||||
this.updateStatusMessage(untrustedDetails || localize('extension limited because of trust requirement', "This extension has limited features because the current workspace is not trusted."));
|
||||
this.updateStatus({ icon: trustIcon, message: untrustedDetails || localize('extension limited because of trust requirement', "This extension has limited features because the current workspace is not trusted.") }, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2167,12 +2087,13 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
if (this.extension.enablementState === EnablementState.DisabledByExtensionKind) {
|
||||
if (!this.extensionsWorkbenchService.installed.some(e => areSameExtensions(e.identifier, this.extension!.identifier) && e.server !== this.extension!.server)) {
|
||||
const server = this.extensionManagementServerService.localExtensionManagementServer === this.extension.server ? this.extensionManagementServerService.remoteExtensionManagementServer : this.extensionManagementServerService.localExtensionManagementServer;
|
||||
this.updateStatusIcon(warningIcon);
|
||||
let message;
|
||||
if (server) {
|
||||
this.updateStatusMessage(localize('Install in other server to enable', "Install the extension on '{0}' to enable.", server.label));
|
||||
message = localize('Install in other server to enable', "Install the extension on '{0}' to enable.", server.label);
|
||||
} else {
|
||||
this.updateStatusMessage(localize('disabled because of extension kind', "This extension has defined that it cannot run on the remote server"));
|
||||
message = localize('disabled because of extension kind', "This extension has defined that it cannot run on the remote server");
|
||||
}
|
||||
this.updateStatus({ icon: warningIcon, message }, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2181,10 +2102,10 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
if (isLanguagePackExtension(this.extension.local.manifest)) {
|
||||
if (!this.extensionsWorkbenchService.installed.some(e => areSameExtensions(e.identifier, this.extension!.identifier) && e.server !== this.extension!.server)) {
|
||||
this.updateStatusIcon(infoIcon);
|
||||
this.updateStatusMessage(this.extension.server === this.extensionManagementServerService.localExtensionManagementServer
|
||||
const message = this.extension.server === this.extensionManagementServerService.localExtensionManagementServer
|
||||
? localize('Install language pack also in remote server', "Install the language pack extension on '{0}' to enable it there also.", this.extensionManagementServerService.remoteExtensionManagementServer.label)
|
||||
: localize('Install language pack also locally', "Install the language pack extension locally to enable it there also."));
|
||||
: localize('Install language pack also locally', "Install the language pack extension locally to enable it there also.");
|
||||
this.updateStatus({ icon: infoIcon, message }, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2193,16 +2114,14 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
const runningExtensionServer = runningExtension ? this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension)) : null;
|
||||
if (this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && runningExtensionServer === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
if (this.extensionManifestPropertiesService.prefersExecuteOnWorkspace(this.extension.local!.manifest)) {
|
||||
this.updateStatusIcon(infoIcon);
|
||||
this.updateStatusMessage(localize('disabled locally', "Extension is enabled on '{0}' and disabled locally.", this.extensionManagementServerService.remoteExtensionManagementServer.label));
|
||||
this.updateStatus({ icon: infoIcon, message: localize('disabled locally', "Extension is enabled on '{0}' and disabled locally.", this.extensionManagementServerService.remoteExtensionManagementServer.label) }, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && runningExtensionServer === this.extensionManagementServerService.localExtensionManagementServer) {
|
||||
if (this.extensionManifestPropertiesService.prefersExecuteOnUI(this.extension.local!.manifest)) {
|
||||
this.updateStatusIcon(infoIcon);
|
||||
this.updateStatusMessage(localize('disabled remotely', "Extension is enabled locally and disabled on '{0}'.", this.extensionManagementServerService.remoteExtensionManagementServer.label));
|
||||
this.updateStatus({ icon: infoIcon, message: localize('disabled remotely', "Extension is enabled locally and disabled on '{0}'.", this.extensionManagementServerService.remoteExtensionManagementServer.label) }, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2210,36 +2129,67 @@ export class ExtensionStatusAction extends ExtensionAction {
|
|||
|
||||
// Extension is disabled by its dependency
|
||||
if (this.extension.enablementState === EnablementState.DisabledByExtensionDependency) {
|
||||
this.updateStatusIcon(warningIcon);
|
||||
this.updateStatusMessage(localize('extension disabled because of dependency', "This extension has been disabled because it depends on an extension that is disabled."));
|
||||
this.updateStatus({ icon: warningIcon, message: localize('extension disabled because of dependency', "This extension has been disabled because it depends on an extension that is disabled.") }, true);
|
||||
return;
|
||||
}
|
||||
|
||||
const isEnabled = this.workbenchExtensionEnablementService.isEnabled(this.extension.local);
|
||||
const isRunning = this._runningExtensions.some(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension!.identifier));
|
||||
|
||||
if (isEnabled && isRunning) {
|
||||
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
|
||||
this.updateStatus({ message: localize('extension enabled on remote', "Extension is enabled on '{0}'", this.extension.server.label) }, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.extension.enablementState === EnablementState.EnabledGlobally) {
|
||||
this.updateStatus({ message: localize('globally enabled', "This extension is enabled globally.") }, true);
|
||||
return;
|
||||
}
|
||||
if (this.extension.enablementState === EnablementState.EnabledWorkspace) {
|
||||
this.updateStatus({ message: localize('workspace enabled', "This extension is enabled for this workspace by the user.") }, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEnabled && !isRunning) {
|
||||
if (this.extension.enablementState === EnablementState.DisabledGlobally) {
|
||||
this.updateStatus({ message: localize('globally disabled', "This extension is disabled globally by the user.") }, true);
|
||||
return;
|
||||
}
|
||||
if (this.extension.enablementState === EnablementState.DisabledWorkspace) {
|
||||
this.updateStatus({ message: localize('workspace disabled', "This extension is disabled for this workspace by the user.") }, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private updateStatusIcon(statusIcon: ThemeIcon): void {
|
||||
this._statusIcon = statusIcon;
|
||||
if (this.statusIcon === errorIcon) {
|
||||
this.class = `${ExtensionStatusAction.CLASS} extension-status-error ${ThemeIcon.asClassName(errorIcon)}`;
|
||||
private updateStatus(status: ExtensionStatus | undefined, updateClass: boolean): void {
|
||||
this._status = status;
|
||||
if (updateClass) {
|
||||
if (this._status?.icon === errorIcon) {
|
||||
this.class = `${ExtensionStatusAction.CLASS} extension-status-error ${ThemeIcon.asClassName(errorIcon)}`;
|
||||
}
|
||||
else if (this._status?.icon === warningIcon) {
|
||||
this.class = `${ExtensionStatusAction.CLASS} extension-status-warning ${ThemeIcon.asClassName(warningIcon)}`;
|
||||
}
|
||||
else if (this._status?.icon === infoIcon) {
|
||||
this.class = `${ExtensionStatusAction.CLASS} extension-status-info ${ThemeIcon.asClassName(infoIcon)}`;
|
||||
}
|
||||
else if (this._status?.icon === trustIcon) {
|
||||
this.class = `${ExtensionStatusAction.CLASS} ${ThemeIcon.asClassName(trustIcon)}`;
|
||||
}
|
||||
else {
|
||||
this.class = `${ExtensionStatusAction.CLASS} hide`;
|
||||
}
|
||||
}
|
||||
if (this.statusIcon === warningIcon) {
|
||||
this.class = `${ExtensionStatusAction.CLASS} extension-status-warning ${ThemeIcon.asClassName(warningIcon)}`;
|
||||
}
|
||||
if (this.statusIcon === infoIcon) {
|
||||
this.class = `${ExtensionStatusAction.CLASS} extension-status-info ${ThemeIcon.asClassName(infoIcon)}`;
|
||||
}
|
||||
if (this.statusIcon === trustIcon) {
|
||||
this.class = `${ExtensionStatusAction.CLASS} ${ThemeIcon.asClassName(trustIcon)}`;
|
||||
}
|
||||
}
|
||||
|
||||
private updateStatusMessage(message: string | undefined): void {
|
||||
this._statusMessage = message;
|
||||
this._onDidChange.fire({});
|
||||
this._onDidChangeStatus.fire();
|
||||
}
|
||||
|
||||
override async run(): Promise<any> {
|
||||
if (this.statusIcon === trustIcon) {
|
||||
if (this._status?.icon === trustIcon) {
|
||||
return this.commandService.executeCommand('workbench.trust.manage');
|
||||
}
|
||||
}
|
||||
|
@ -2687,6 +2637,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
|||
collector.addRule(`.extension-list-item .monaco-action-bar .action-item .action-label.extension-action.extension-status-error { color: ${errorColor}; }`);
|
||||
collector.addRule(`.extension-editor .monaco-action-bar .action-item .action-label.extension-action.extension-status-error { color: ${errorColor}; }`);
|
||||
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(errorIcon)} { color: ${errorColor}; }`);
|
||||
collector.addRule(`.monaco-workbench .extension-editor > .header > .details > .actions > .status ${ThemeIcon.asCSSSelector(errorIcon)} { color: ${errorColor}; }`);
|
||||
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(errorIcon)} { color: ${errorColor}; }`);
|
||||
}
|
||||
|
||||
|
@ -2695,6 +2646,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
|||
collector.addRule(`.extension-list-item .monaco-action-bar .action-item .action-label.extension-action.extension-status-warning { color: ${warningColor}; }`);
|
||||
collector.addRule(`.extension-editor .monaco-action-bar .action-item .action-label.extension-action.extension-status-warning { color: ${warningColor}; }`);
|
||||
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(warningIcon)} { color: ${warningColor}; }`);
|
||||
collector.addRule(`.monaco-workbench .extension-editor > .header > .details > .actions > .status ${ThemeIcon.asCSSSelector(warningIcon)} { color: ${warningColor}; }`);
|
||||
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(warningIcon)} { color: ${warningColor}; }`);
|
||||
}
|
||||
|
||||
|
@ -2703,6 +2655,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
|||
collector.addRule(`.extension-list-item .monaco-action-bar .action-item .action-label.extension-action.extension-status-info { color: ${infoColor}; }`);
|
||||
collector.addRule(`.extension-editor .monaco-action-bar .action-item .action-label.extension-action.extension-status-info { color: ${infoColor}; }`);
|
||||
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(infoIcon)} { color: ${infoColor}; }`);
|
||||
collector.addRule(`.monaco-workbench .extension-editor > .header > .details > .actions > .status ${ThemeIcon.asCSSSelector(infoIcon)} { color: ${infoColor}; }`);
|
||||
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(infoIcon)} { color: ${infoColor}; }`);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -13,7 +13,7 @@ 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 { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { UpdateAction, ManageExtensionAction, ReloadAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, ExtensionToolTipAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { UpdateAction, ManageExtensionAction, ReloadAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, ExtensionPackCountWidget as ExtensionPackBadgeWidget, SyncIgnoredWidget, ExtensionHoverWidget, ExtensionActivationStatusWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
|
||||
import { IExtensionService, toExtension } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
@ -125,8 +125,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
|
|||
extensionStatusIconAction,
|
||||
this.instantiationService.createInstance(ManageExtensionAction)
|
||||
];
|
||||
const extensionTooltipAction = this.instantiationService.createInstance(ExtensionToolTipAction, extensionStatusIconAction, reloadAction);
|
||||
const extensionHoverWidget = this.instantiationService.createInstance(ExtensionHoverWidget, { target: root, position: this.options.hoverOptions.position }, extensionStatusIconAction, extensionTooltipAction);
|
||||
const extensionHoverWidget = this.instantiationService.createInstance(ExtensionHoverWidget, { target: root, position: this.options.hoverOptions.position }, extensionStatusIconAction, reloadAction);
|
||||
|
||||
const widgets = [
|
||||
recommendationWidget,
|
||||
|
@ -139,10 +138,10 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
|
|||
this.instantiationService.createInstance(InstallCountWidget, installCount, true),
|
||||
this.instantiationService.createInstance(RatingsWidget, ratings, true),
|
||||
];
|
||||
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets, extensionTooltipAction]);
|
||||
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets]);
|
||||
|
||||
actionbar.push(actions, actionOptions);
|
||||
const disposable = combinedDisposable(...actions, ...widgets, actionbar, extensionContainers, extensionTooltipAction);
|
||||
const disposable = combinedDisposable(...actions, ...widgets, actionbar, extensionContainers);
|
||||
|
||||
return {
|
||||
root, element, icon, name, installCount, ratings, description, author, disposables: [disposable], actionbar,
|
||||
|
|
|
@ -12,8 +12,8 @@ import { localize } from 'vs/nls';
|
|||
import { EnablementState, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { extensionButtonProminentBackground, extensionButtonProminentForeground, ExtensionStatusAction, ExtensionToolTipAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IThemeService, IColorTheme, ThemeIcon, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { extensionButtonProminentBackground, extensionButtonProminentForeground, ExtensionStatusAction, ReloadAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IThemeService, ThemeIcon, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -31,6 +31,7 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens
|
|||
import Severity from 'vs/base/common/severity';
|
||||
import { setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
|
||||
export abstract class ExtensionWidget extends Disposable implements IExtensionContainer {
|
||||
private _extension: IExtension | null = null;
|
||||
|
@ -165,7 +166,6 @@ export class RecommendationWidget extends ExtensionWidget {
|
|||
|
||||
constructor(
|
||||
private parent: HTMLElement,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IExtensionRecommendationsService private readonly extensionRecommendationsService: IExtensionRecommendationsService
|
||||
) {
|
||||
super();
|
||||
|
@ -192,14 +192,6 @@ export class RecommendationWidget extends ExtensionWidget {
|
|||
this.element = append(this.parent, $('div.extension-bookmark'));
|
||||
const recommendation = append(this.element, $('.recommendation'));
|
||||
append(recommendation, $('span' + ThemeIcon.asCSSSelector(ratingIcon)));
|
||||
const applyBookmarkStyle = (theme: IColorTheme) => {
|
||||
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.getColorTheme());
|
||||
this.themeService.onDidColorThemeChange(applyBookmarkStyle, this, this.disposables);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,8 +381,8 @@ export class ExtensionHoverWidget extends ExtensionWidget {
|
|||
|
||||
constructor(
|
||||
private readonly options: ExtensionHoverOptions,
|
||||
private readonly extensionStatusIconAction: ExtensionStatusAction,
|
||||
private readonly tooltipAction: ExtensionToolTipAction,
|
||||
private readonly extensionStatusAction: ExtensionStatusAction,
|
||||
private readonly reloadAction: ReloadAction,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@IHoverService private readonly hoverService: IHoverService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
|
@ -426,32 +418,22 @@ export class ExtensionHoverWidget extends ExtensionWidget {
|
|||
markdown.appendMarkdown(`**${this.extension.displayName}** _v${this.extension.version}_`);
|
||||
markdown.appendText(`\n`);
|
||||
|
||||
const toolTip = this.tooltipAction.label;
|
||||
const extensionStatus = this.extensionsWorkbenchService.getExtensionStatus(this.extension);
|
||||
const extensionRuntimeStatus = this.extensionsWorkbenchService.getExtensionStatus(this.extension);
|
||||
const extensionStatus = this.extensionStatusAction.status;
|
||||
const reloadRequiredMessage = this.reloadAction.enabled ? this.reloadAction.tooltip : '';
|
||||
|
||||
if (toolTip || extensionStatus) {
|
||||
if (toolTip) {
|
||||
if (this.extensionStatusIconAction.statusIcon) {
|
||||
markdown.appendMarkdown(`$(${this.extensionStatusIconAction.statusIcon.id}) `);
|
||||
}
|
||||
markdown.appendMarkdown(`${toolTip}`);
|
||||
if (this.extension.enablementState === EnablementState.DisabledByExtensionDependency && this.extension.local) {
|
||||
markdown.appendMarkdown(` [${localize('dependencies', "Show Dependencies")}](${URI.parse(`command:extension.open?${encodeURIComponent(JSON.stringify([this.extension.identifier.id, ExtensionEditorTab.Dependencies]))}`)})`);
|
||||
}
|
||||
markdown.appendText(`\n`);
|
||||
}
|
||||
|
||||
if (extensionStatus) {
|
||||
if (extensionStatus.activationTimes) {
|
||||
const activationTime = extensionStatus.activationTimes.codeLoadingTime + extensionStatus.activationTimes.activateCallTime;
|
||||
markdown.appendMarkdown(`${localize('activation', "Activation time")}${extensionStatus.activationTimes.activationReason.startup ? ` (${localize('startup', "Startup")})` : ''} : \`${activationTime}ms\``);
|
||||
if (extensionRuntimeStatus || extensionStatus || reloadRequiredMessage) {
|
||||
if (extensionRuntimeStatus) {
|
||||
if (extensionRuntimeStatus.activationTimes) {
|
||||
const activationTime = extensionRuntimeStatus.activationTimes.codeLoadingTime + extensionRuntimeStatus.activationTimes.activateCallTime;
|
||||
markdown.appendMarkdown(`${localize('activation', "Activation time")}${extensionRuntimeStatus.activationTimes.activationReason.startup ? ` (${localize('startup', "Startup")})` : ''} : \`${activationTime}ms\``);
|
||||
markdown.appendText(`\n`);
|
||||
}
|
||||
if (extensionStatus.runtimeErrors.length || extensionStatus.messages.length) {
|
||||
const hasErrors = extensionStatus.runtimeErrors.length || extensionStatus.messages.some(message => message.type === Severity.Error);
|
||||
const hasWarnings = extensionStatus.messages.some(message => message.type === Severity.Warning);
|
||||
const errorsLink = extensionStatus.runtimeErrors.length ? `[${extensionStatus.runtimeErrors.length === 1 ? localize('uncaught error', '1 uncaught error') : localize('uncaught errors', '{0} uncaught errors', extensionStatus.runtimeErrors.length)}](${URI.parse(`command:extension.open?${encodeURIComponent(JSON.stringify([this.extension.identifier.id, ExtensionEditorTab.RuntimeStatus]))}`)})` : undefined;
|
||||
const messageLink = extensionStatus.messages.length ? `[${extensionStatus.messages.length === 1 ? localize('message', '1 message') : localize('messages', '{0} messages', extensionStatus.messages.length)}](${URI.parse(`command:extension.open?${encodeURIComponent(JSON.stringify([this.extension.identifier.id, ExtensionEditorTab.RuntimeStatus]))}`)})` : undefined;
|
||||
if (extensionRuntimeStatus.runtimeErrors.length || extensionRuntimeStatus.messages.length) {
|
||||
const hasErrors = extensionRuntimeStatus.runtimeErrors.length || extensionRuntimeStatus.messages.some(message => message.type === Severity.Error);
|
||||
const hasWarnings = extensionRuntimeStatus.messages.some(message => message.type === Severity.Warning);
|
||||
const errorsLink = extensionRuntimeStatus.runtimeErrors.length ? `[${extensionRuntimeStatus.runtimeErrors.length === 1 ? localize('uncaught error', '1 uncaught error') : localize('uncaught errors', '{0} uncaught errors', extensionRuntimeStatus.runtimeErrors.length)}](${URI.parse(`command:extension.open?${encodeURIComponent(JSON.stringify([this.extension.identifier.id, ExtensionEditorTab.RuntimeStatus]))}`)})` : undefined;
|
||||
const messageLink = extensionRuntimeStatus.messages.length ? `[${extensionRuntimeStatus.messages.length === 1 ? localize('message', '1 message') : localize('messages', '{0} messages', extensionRuntimeStatus.messages.length)}](${URI.parse(`command:extension.open?${encodeURIComponent(JSON.stringify([this.extension.identifier.id, ExtensionEditorTab.RuntimeStatus]))}`)})` : undefined;
|
||||
markdown.appendMarkdown(`$(${hasErrors ? errorIcon.id : hasWarnings ? warningIcon.id : infoIcon.id}) This extension has reported `);
|
||||
if (errorsLink && messageLink) {
|
||||
markdown.appendMarkdown(`${errorsLink} and ${messageLink}`);
|
||||
|
@ -462,6 +444,27 @@ export class ExtensionHoverWidget extends ExtensionWidget {
|
|||
}
|
||||
}
|
||||
|
||||
if (extensionStatus) {
|
||||
if (extensionStatus.icon) {
|
||||
markdown.appendMarkdown(`$(${extensionStatus.icon.id}) `);
|
||||
}
|
||||
if (isString(extensionStatus.message)) {
|
||||
markdown.appendText(extensionStatus.message);
|
||||
} else {
|
||||
markdown.appendMarkdown(extensionStatus.message.value);
|
||||
}
|
||||
if (this.extension.enablementState === EnablementState.DisabledByExtensionDependency && this.extension.local) {
|
||||
markdown.appendMarkdown(` [${localize('dependencies', "Show Dependencies")}](${URI.parse(`command:extension.open?${encodeURIComponent(JSON.stringify([this.extension.identifier.id, ExtensionEditorTab.Dependencies]))}`)})`);
|
||||
}
|
||||
markdown.appendText(`\n`);
|
||||
}
|
||||
|
||||
if (reloadRequiredMessage) {
|
||||
markdown.appendMarkdown(`$(${infoIcon.id}) `);
|
||||
markdown.appendMarkdown(`${reloadRequiredMessage}`);
|
||||
markdown.appendText(`\n`);
|
||||
}
|
||||
|
||||
markdown.appendMarkdown(`---`);
|
||||
markdown.appendText(`\n`);
|
||||
}
|
||||
|
@ -499,4 +502,15 @@ registerThemingParticipant((theme, collector) => {
|
|||
if (extensionRatingIcon) {
|
||||
collector.addRule(`.extension-ratings .codicon-extensions-star-full, .extension-ratings .codicon-extensions-star-half { color: ${extensionRatingIcon}; }`);
|
||||
}
|
||||
|
||||
const fgColor = theme.getColor(extensionButtonProminentForeground);
|
||||
if (fgColor) {
|
||||
collector.addRule(`.extension-bookmark .recommendation { color: ${fgColor}; }`);
|
||||
collector.addRule(`.monaco-workbench .extension-editor > .header > .details > .recommendation .codicon { color: ${fgColor}; }`);
|
||||
}
|
||||
|
||||
const bgColor = theme.getColor(extensionButtonProminentBackground);
|
||||
if (bgColor) {
|
||||
collector.addRule(`.extension-bookmark .recommendation { border-top-color: ${bgColor}; }`);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -144,6 +144,7 @@
|
|||
|
||||
.extension-editor > .header > .details > .actions {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar {
|
||||
|
@ -198,44 +199,48 @@
|
|||
margin-right: 0;
|
||||
}
|
||||
|
||||
.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.extension-status-label,
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar .action-item .action-label.disable-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.extension-status-label:hover,
|
||||
.extension-editor > .header > .details > .actions > .monaco-action-bar .action-item .action-label.disable-status:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtext-container {
|
||||
display: block;
|
||||
float: left;
|
||||
margin-top: 0;
|
||||
font-size: 13px;
|
||||
font-style: italic;
|
||||
.extension-editor > .header > .details > .actions > .status {
|
||||
line-height: 22px;
|
||||
font-size: 90%;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtext-container > .monaco-action-bar {
|
||||
float: left;
|
||||
margin-top: 2px;
|
||||
font-style: normal;
|
||||
.extension-editor > .header > .details > .actions > .status p {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtext-container > .subtext {
|
||||
float:left;
|
||||
.extension-editor > .header > .details > .actions > .status a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .actions > .status span {
|
||||
vertical-align: middle;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .recommendation {
|
||||
margin-top: 5px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.extension-editor > .header > .details > .subtext-container > .monaco-action-bar .action-label {
|
||||
margin-top: 4px;
|
||||
margin-left: 4px;
|
||||
padding-bottom: 1px;
|
||||
.extension-editor > .header > .details > .recommendation .codicon {
|
||||
font-size: inherit;
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
.extension-editor > .header.recommended > .details > .recommendation > .monaco-action-bar .actions-container {
|
||||
justify-content: flex-start;
|
||||
.extension-editor > .header > .details > .recommendation .recommendation-text {
|
||||
vertical-align: text-bottom;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.extension-editor > .body {
|
||||
|
|
Loading…
Reference in a new issue