From fd83e2135cc22d69d6d47f064c3a984b79b74c5b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 26 Nov 2021 20:02:54 +0100 Subject: [PATCH] #15756 show pre-release text in extension editor --- .../extensions/browser/extensionEditor.ts | 61 ++++++++++++++----- .../extensions/browser/extensionsWidgets.ts | 11 ++-- .../browser/media/extensionEditor.css | 18 ++++++ .../browser/media/extensionsWidgets.css | 2 +- 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts index 25ae36d54c6..6b8d4842712 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts @@ -23,7 +23,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes'; import { ResolvedKeybinding } from 'vs/base/common/keybindings'; import { ExtensionsInput, IExtensionEditorOptions } from 'vs/workbench/contrib/extensions/common/extensionsInput'; import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, IExtension, ExtensionContainers, ExtensionEditorTab, ExtensionState } from 'vs/workbench/contrib/extensions/common/extensions'; -import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget, PreReleaseIndicatorWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets'; +import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget, PreReleaseIndicatorWidget, ExtensionHoverWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets'; import { IEditorOpenContext } from 'vs/workbench/common/editor'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { @@ -68,7 +68,7 @@ import { Delegate } from 'vs/workbench/contrib/extensions/browser/extensionsList import { renderMarkdown } from 'vs/base/browser/markdownRenderer'; import { attachKeybindingLabelStyler } from 'vs/platform/theme/common/styler'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { errorIcon, infoIcon, starEmptyIcon, verifiedPublisherIcon as verifiedPublisherThemeIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons'; +import { errorIcon, infoIcon, preReleaseIcon, starEmptyIcon, verifiedPublisherIcon as verifiedPublisherThemeIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons'; import { MarkdownString } from 'vs/base/common/htmlContent'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; import { ViewContainerLocation } from 'vs/workbench/common/views'; @@ -150,6 +150,7 @@ interface IExtensionEditorTemplate { actionsAndStatusContainer: HTMLElement; extensionActionBar: ActionBar; status: HTMLElement; + preReleaseText: HTMLElement; recommendation: HTMLElement; navbar: NavBar; content: HTMLElement; @@ -254,6 +255,7 @@ export class ExtensionEditor extends EditorPane { rating.setAttribute('role', 'link'); // #132645 const description = append(details, $('.description')); + const preReleaseText = append(details, $('.pre-release-text')); const actionsAndStatusContainer = append(details, $('.actions-status-container')); const extensionActionBar = this._register(new ActionBar(actionsAndStatusContainer, { @@ -303,6 +305,7 @@ export class ExtensionEditor extends EditorPane { rating, actionsAndStatusContainer, extensionActionBar, + preReleaseText, status, recommendation }; @@ -476,6 +479,7 @@ export class ExtensionEditor extends EditorPane { this.transientDisposables.add(disposable); } + this.setPreReleaseText(extension, template); this.setStatus(extension, extensionStatus, template); this.setRecommendationText(extension, template); @@ -524,6 +528,30 @@ export class ExtensionEditor extends EditorPane { this.editorLoadComplete = true; } + private setPreReleaseText(extension: IExtension, template: IExtensionEditorTemplate): void { + let preReleaseText: string | undefined; + reset(template.preReleaseText); + const disposables = this.transientDisposables.add(new DisposableStore()); + const updatePreReleaseText = () => { + const newPreReleaseText = ExtensionHoverWidget.getPreReleaseMessage(extension); + if (preReleaseText !== newPreReleaseText) { + preReleaseText = newPreReleaseText; + disposables.clear(); + reset(template.preReleaseText); + if (preReleaseText) { + append(template.preReleaseText, $(`span${ThemeIcon.asCSSSelector(preReleaseIcon)}`)); + disposables.add(this.renderMarkdownText(preReleaseText, template.preReleaseText)); + } + } + }; + updatePreReleaseText(); + this.transientDisposables.add(this.extensionsWorkbenchService.onChange(e => { + if (e && areSameExtensions(e.identifier, extension.identifier)) { + updatePreReleaseText(); + } + })); + } + private setStatus(extension: IExtension, extensionStatus: ExtensionStatusAction, template: IExtensionEditorTemplate): void { const disposables = new DisposableStore(); this.transientDisposables.add(disposables); @@ -536,16 +564,7 @@ export class ExtensionEditor extends EditorPane { const statusIconActionBar = disposables.add(new ActionBar(template.status, { animated: false })); statusIconActionBar.push(extensionStatus, { icon: true, label: false }); } - const rendered = disposables.add(renderMarkdown(new MarkdownString(status.message.value, { isTrusted: true, supportThemeIcons: true }), { - actionHandler: { - callback: (content) => { - this.openerService.open(content, { allowCommands: true }).catch(onUnexpectedError); - }, - disposables: disposables - } - })); - append(append(template.status, $('.status-text')), - rendered.element); + disposables.add(this.renderMarkdownText(status.message.value, append(template.status, $('.status-text')))); } }; updateStatus(); @@ -574,6 +593,20 @@ export class ExtensionEditor extends EditorPane { this.transientDisposables.add(this.extensionRecommendationsService.onDidChangeRecommendations(() => updateRecommendationText())); } + private renderMarkdownText(markdownText: string, parent: HTMLElement): IDisposable { + const disposables = new DisposableStore(); + const rendered = disposables.add(renderMarkdown(new MarkdownString(markdownText, { isTrusted: true, supportThemeIcons: true }), { + actionHandler: { + callback: (content) => { + this.openerService.open(content, { allowCommands: true }).catch(onUnexpectedError); + }, + disposables: disposables + } + })); + append(parent, rendered.element); + return disposables; + } + override clearInput(): void { this.contentDisposables.clear(); this.transientDisposables.clear(); @@ -1769,7 +1802,6 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = if (link) { collector.addRule(`.monaco-workbench .extension-editor .content .details .additional-details-container .resources-container a { color: ${link}; }`); collector.addRule(`.monaco-workbench .extension-editor .content .feature-contributions a { color: ${link}; }`); - collector.addRule(`.monaco-workbench .extension-editor > .header > .details > .actions-status-container > .status > .status-text a { color: ${link}; }`); } const activeLink = theme.getColor(textLinkActiveForeground); @@ -1778,9 +1810,6 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = .monaco-workbench .extension-editor .content .details .additional-details-container .resources-container a:active { color: ${activeLink}; }`); collector.addRule(`.monaco-workbench .extension-editor .content .feature-contributions a:hover, .monaco-workbench .extension-editor .content .feature-contributions a:active { color: ${activeLink}; }`); - collector.addRule(`.monaco-workbench .extension-editor > .header > .details > .actions-status-container > .status > .status-text a:hover, - .monaco-workbench .extension-editor > .header > .details > actions-status-container > .status > .status-text a:active { color: ${activeLink}; }`); - } const buttonHoverBackgroundColor = theme.getColor(buttonHoverBackground); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts index 203a7372790..a7251b84880 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.ts @@ -500,9 +500,10 @@ export class ExtensionHoverWidget extends ExtensionWidget { markdown.appendText(`\n`); } - const preReleaseMessage = this.getPreReleaseMessage(this.extension); + const preReleaseMessage = ExtensionHoverWidget.getPreReleaseMessage(this.extension); if (preReleaseMessage) { - markdown.appendMarkdown(preReleaseMessage); + const extensionPreReleaseIcon = this.themeService.getColorTheme().getColor(extensionPreReleaseIconColor); + markdown.appendMarkdown(`$(${preReleaseIcon.id}) ${preReleaseMessage}`); markdown.appendText(`\n`); } @@ -575,17 +576,15 @@ export class ExtensionHoverWidget extends ExtensionWidget { return `$(${starEmptyIcon.id}) ${recommendation.reasonText}`; } - private getPreReleaseMessage(extension: IExtension): string | undefined { + static getPreReleaseMessage(extension: IExtension): string | undefined { if (!extension.hasPreReleaseVersion) { return undefined; } if (extension.local?.isPreReleaseVersion || extension.gallery?.properties.isPreReleaseVersion) { return undefined; } - const extensionPreReleaseIcon = this.themeService.getColorTheme().getColor(extensionPreReleaseIconColor); const preReleaseVersionLink = `[${localize('Show prerelease version', "Pre-Release version")}](${URI.parse(`command:workbench.extensions.action.showPreReleaseVersion?${encodeURIComponent(JSON.stringify([extension.identifier.id]))}`)})`; - const message = localize('has prerelease', "This extension has a {0} available", preReleaseVersionLink); - return `$(${preReleaseIcon.id}) ${message}`; + return localize('has prerelease', "This extension has a {0} available", preReleaseVersionLink); } } diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css index af3cb435d00..572237f365a 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css @@ -261,13 +261,31 @@ margin-top: 2px; } +.extension-editor > .header > .details > .pre-release-text p, .extension-editor > .header > .details > .actions-status-container > .status > .status-text p { margin-top: 0px; margin-bottom: 0px; } +.extension-editor > .header > .details > .pre-release-text a, +.extension-editor > .header > .details > .actions-status-container > .status > .status-text a { + color: var(--vscode-textLink-foreground) +} + +.extension-editor > .header > .details > .pre-release-text a:hover, .extension-editor > .header > .details > .actions-status-container > .status > .status-text a:hover { text-decoration: underline; + color: var(--vscode-textLink-activeForeground) +} + +.extension-editor > .header > .details > .pre-release-text a:active, +.extension-editor > .header > .details > .actions-status-container > .status > .status-text a:active { + color: var(--vscode-textLink-activeForeground) +} + +.extension-editor > .header > .details > .pre-release-text:not(:empty){ + margin-top: 10px; + display: flex; } .extension-editor > .header > .details > .recommendation { diff --git a/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css b/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css index dd487b3e73a..3c58e5f40af 100644 --- a/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css +++ b/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css @@ -60,6 +60,6 @@ } /* codicon colors */ -.codicon .codicon-extensions-pre-release { +.codicon.codicon-extensions-pre-release { color: var(--vscode-extensionIcon-preReleaseForeground); }