Skip to content

Commit 49fd0a2

Browse files
authored
prepare to use extensions codicon for default icon (microsoft#249977)
* prepare to use extensions codicon for default icon * fix tests
1 parent 194bb1f commit 49fd0a2

File tree

14 files changed

+130
-108
lines changed

14 files changed

+130
-108
lines changed

src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { $, Dimension, addDisposableListener, append, clearNode } from '../../../../base/browser/dom.js';
6+
import { $, Dimension, append, clearNode } from '../../../../base/browser/dom.js';
77
import { ActionBar } from '../../../../base/browser/ui/actionbar/actionbar.js';
88
import { getDefaultHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegateFactory.js';
99
import { renderLabelWithIcons } from '../../../../base/browser/ui/iconLabel/iconLabels.js';
@@ -38,12 +38,13 @@ import { IEditorGroup } from '../../../services/editor/common/editorGroupsServic
3838
import { IEditorService } from '../../../services/editor/common/editorService.js';
3939
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
4040
import { Extensions, IExtensionFeaturesManagementService, IExtensionFeaturesRegistry } from '../../../services/extensionManagement/common/extensionFeatures.js';
41-
import { DefaultIconPath, EnablementState } from '../../../services/extensionManagement/common/extensionManagement.js';
41+
import { EnablementState } from '../../../services/extensionManagement/common/extensionManagement.js';
4242
import { LocalWebWorkerRunningLocation } from '../../../services/extensions/common/extensionRunningLocation.js';
4343
import { IExtensionHostProfile, IExtensionService, IExtensionsStatus } from '../../../services/extensions/common/extensions.js';
4444
import { IExtension, IExtensionsWorkbenchService } from '../common/extensions.js';
4545
import { RuntimeExtensionsInput } from '../common/runtimeExtensionsInput.js';
4646
import { errorIcon, warningIcon } from './extensionsIcons.js';
47+
import { ExtensionIconWidget } from './extensionsWidgets.js';
4748
import './media/runtimeExtensionsEditor.css';
4849

4950
interface IExtensionProfileInformation {
@@ -221,7 +222,6 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane {
221222
interface IRuntimeExtensionTemplateData {
222223
root: HTMLElement;
223224
element: HTMLElement;
224-
icon: HTMLImageElement;
225225
name: HTMLElement;
226226
version: HTMLElement;
227227
msgContainer: HTMLElement;
@@ -230,14 +230,15 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane {
230230
profileTime: HTMLElement;
231231
disposables: IDisposable[];
232232
elementDisposables: IDisposable[];
233+
extension: IExtension | undefined;
233234
}
234235

235236
const renderer: IListRenderer<IRuntimeExtension, IRuntimeExtensionTemplateData> = {
236237
templateId: TEMPLATE_ID,
237238
renderTemplate: (root: HTMLElement): IRuntimeExtensionTemplateData => {
238239
const element = append(root, $('.extension'));
239240
const iconContainer = append(element, $('.icon-container'));
240-
const icon = append(iconContainer, $<HTMLImageElement>('img.icon'));
241+
const extensionIconWidget = this._instantiationService.createInstance(ExtensionIconWidget, iconContainer);
241242

242243
const desc = append(element, $('div.desc'));
243244
const headerContainer = append(desc, $('.header-container'));
@@ -254,18 +255,20 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane {
254255
const activationTime = append(timeContainer, $('div.activation-time'));
255256
const profileTime = append(timeContainer, $('div.profile-time'));
256257

257-
const disposables = [actionbar, listener];
258+
const disposables = [extensionIconWidget, actionbar, listener];
258259

259260
return {
260261
root,
261262
element,
262-
icon,
263263
name,
264264
version,
265265
actionbar,
266266
activationTime,
267267
profileTime,
268268
msgContainer,
269+
set extension(extension: IExtension | undefined) {
270+
extensionIconWidget.extension = extension || null;
271+
},
269272
disposables,
270273
elementDisposables: [],
271274
};
@@ -274,18 +277,10 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane {
274277
renderElement: (element: IRuntimeExtension, index: number, data: IRuntimeExtensionTemplateData): void => {
275278

276279
data.elementDisposables = dispose(data.elementDisposables);
280+
data.extension = element.marketplaceInfo;
277281

278282
data.root.classList.toggle('odd', index % 2 === 1);
279283

280-
data.elementDisposables.push(addDisposableListener(data.icon, 'error', () => data.icon.src = element.marketplaceInfo?.iconUrlFallback || DefaultIconPath, { once: true }));
281-
data.icon.src = element.marketplaceInfo?.iconUrl || DefaultIconPath;
282-
283-
if (!data.icon.complete) {
284-
data.icon.style.visibility = 'hidden';
285-
data.icon.onload = () => data.icon.style.visibility = 'inherit';
286-
} else {
287-
data.icon.style.visibility = 'inherit';
288-
}
289284
data.name.textContent = (element.marketplaceInfo?.displayName || element.description.identifier.value).substr(0, 50);
290285
data.version.textContent = element.description.version;
291286

src/vs/workbench/contrib/extensions/browser/extensionEditor.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { $, Dimension, addDisposableListener, append, hide, setParentFlowTo, show } from '../../../../base/browser/dom.js';
6+
import { $, Dimension, append, hide, setParentFlowTo, show } from '../../../../base/browser/dom.js';
77
import { ActionBar } from '../../../../base/browser/ui/actionbar/actionbar.js';
88
import { getDefaultHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegateFactory.js';
99
import { DomScrollableElement } from '../../../../base/browser/ui/scrollbar/scrollableElement.js';
@@ -72,7 +72,7 @@ import {
7272
} from './extensionsActions.js';
7373
import { Delegate } from './extensionsList.js';
7474
import { ExtensionData, ExtensionsGridView, ExtensionsTree, getExtensions } from './extensionsViewer.js';
75-
import { ExtensionRecommendationWidget, ExtensionStatusWidget, ExtensionWidget, InstallCountWidget, RatingsWidget, RemoteBadgeWidget, SponsorWidget, PublisherWidget, onClick, ExtensionKindIndicatorWidget } from './extensionsWidgets.js';
75+
import { ExtensionRecommendationWidget, ExtensionStatusWidget, ExtensionWidget, InstallCountWidget, RatingsWidget, RemoteBadgeWidget, SponsorWidget, PublisherWidget, onClick, ExtensionKindIndicatorWidget, ExtensionIconWidget } from './extensionsWidgets.js';
7676
import { ExtensionContainers, ExtensionEditorTab, ExtensionState, IExtension, IExtensionContainer, IExtensionsWorkbenchService } from '../common/extensions.js';
7777
import { ExtensionsInput, IExtensionEditorOptions } from '../common/extensionsInput.js';
7878
import { DEFAULT_MARKDOWN_STYLES, renderMarkdownDocument } from '../../markdown/browser/markdownDocumentRenderer.js';
@@ -153,8 +153,6 @@ interface IActiveElement {
153153
}
154154

155155
interface IExtensionEditorTemplate {
156-
iconContainer: HTMLElement;
157-
icon: HTMLImageElement;
158156
name: HTMLElement;
159157
preview: HTMLElement;
160158
builtin: HTMLElement;
@@ -273,7 +271,7 @@ export class ExtensionEditor extends EditorPane {
273271
const header = append(root, $('.header'));
274272

275273
const iconContainer = append(header, $('.icon-container'));
276-
const icon = append(iconContainer, $<HTMLImageElement>('img.icon', { draggable: false, alt: '' }));
274+
const iconWidget = this.instantiationService.createInstance(ExtensionIconWidget, iconContainer);
277275
const remoteBadge = this.instantiationService.createInstance(RemoteBadgeWidget, iconContainer, true);
278276

279277
const details = append(header, $('.details'));
@@ -313,6 +311,7 @@ export class ExtensionEditor extends EditorPane {
313311
const sponsorWidget = this.instantiationService.createInstance(SponsorWidget, sponsorContainer);
314312

315313
const widgets: ExtensionWidget[] = [
314+
iconWidget,
316315
remoteBadge,
317316
versionWidget,
318317
publisherWidget,
@@ -430,8 +429,6 @@ export class ExtensionEditor extends EditorPane {
430429
content,
431430
description,
432431
header,
433-
icon,
434-
iconContainer,
435432
name,
436433
navbar,
437434
preview,
@@ -545,9 +542,6 @@ export class ExtensionEditor extends EditorPane {
545542
template.gallery = gallery;
546543
template.manifest = null;
547544

548-
this.transientDisposables.add(addDisposableListener(template.icon, 'error', () => template.icon.src = extension.iconUrlFallback, { once: true }));
549-
template.icon.src = extension.iconUrl;
550-
551545
template.name.textContent = extension.displayName;
552546
template.name.classList.toggle('clickable', !!extension.url);
553547
template.name.classList.toggle('deprecated', !!extension.deprecationInfo);

src/vs/workbench/contrib/extensions/browser/extensionsList.ts

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import './media/extension.css';
7-
import { append, $, addDisposableListener } from '../../../../base/browser/dom.js';
7+
import { append, $ } from '../../../../base/browser/dom.js';
88
import { IDisposable, dispose, combinedDisposable } from '../../../../base/common/lifecycle.js';
99
import { IAction } from '../../../../base/common/actions.js';
1010
import { ActionBar } from '../../../../base/browser/ui/actionbar/actionbar.js';
@@ -14,7 +14,7 @@ import { IPagedRenderer } from '../../../../base/browser/ui/list/listPaging.js';
1414
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService, IExtensionsViewState } from '../common/extensions.js';
1515
import { ManageExtensionAction, ExtensionRuntimeStateAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ButtonWithDropDownExtensionAction, InstallDropdownAction, InstallingLabelAction, ButtonWithDropdownExtensionActionViewItem, DropDownExtensionAction, WebInstallAction, MigrateDeprecatedExtensionAction, SetLanguageAction, ClearLanguageAction, UpdateAction } from './extensionsActions.js';
1616
import { areSameExtensions } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js';
17-
import { RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, ExtensionPackCountWidget as ExtensionPackBadgeWidget, SyncIgnoredWidget, ExtensionHoverWidget, ExtensionRuntimeStatusWidget, PreReleaseBookmarkWidget, PublisherWidget, ExtensionKindIndicatorWidget } from './extensionsWidgets.js';
17+
import { RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, ExtensionPackCountWidget as ExtensionPackBadgeWidget, SyncIgnoredWidget, ExtensionHoverWidget, ExtensionRuntimeStatusWidget, PreReleaseBookmarkWidget, PublisherWidget, ExtensionKindIndicatorWidget, ExtensionIconWidget } from './extensionsWidgets.js';
1818
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
1919
import { IWorkbenchExtensionEnablementService } from '../../../services/extensionManagement/common/extensionManagement.js';
2020
import { INotificationService } from '../../../../platform/notification/common/notification.js';
@@ -31,7 +31,6 @@ const EXTENSION_LIST_ELEMENT_HEIGHT = 72;
3131
export interface ITemplateData {
3232
root: HTMLElement;
3333
element: HTMLElement;
34-
icon: HTMLImageElement;
3534
name: HTMLElement;
3635
description: HTMLElement;
3736
installCount: HTMLElement;
@@ -73,7 +72,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
7372
const preReleaseWidget = this.instantiationService.createInstance(PreReleaseBookmarkWidget, append(root, $('.extension-bookmark-container')));
7473
const element = append(root, $('.extension-list-item'));
7574
const iconContainer = append(element, $('.icon-container'));
76-
const icon = append(iconContainer, $<HTMLImageElement>('img.icon', { alt: '' }));
75+
const iconWidget = this.instantiationService.createInstance(ExtensionIconWidget, iconContainer);
7776
const iconRemoteBadgeWidget = this.instantiationService.createInstance(RemoteBadgeWidget, iconContainer, false);
7877
const extensionPackBadgeWidget = this.instantiationService.createInstance(ExtensionPackBadgeWidget, iconContainer);
7978
const details = append(element, $('.details'));
@@ -85,7 +84,6 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
8584
const syncIgnore = append(header, $('span.sync-ignored'));
8685
const extensionKindIndicator = append(header, $('span'));
8786
const activationStatus = append(header, $('span.activation-status'));
88-
const headerRemoteBadgeWidget = this.instantiationService.createInstance(RemoteBadgeWidget, header, false);
8987
const description = append(details, $('.description.ellipsis'));
9088
const footer = append(details, $('.footer'));
9189
const publisherWidget = this.instantiationService.createInstance(PublisherWidget, append(footer, $('.publisher-container')), true);
@@ -132,11 +130,11 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
132130
const extensionHoverWidget = this.instantiationService.createInstance(ExtensionHoverWidget, { target: root, position: this.options.hoverOptions.position }, extensionStatusIconAction);
133131

134132
const widgets = [
133+
iconWidget,
135134
recommendationWidget,
136135
preReleaseWidget,
137136
iconRemoteBadgeWidget,
138137
extensionPackBadgeWidget,
139-
headerRemoteBadgeWidget,
140138
publisherWidget,
141139
extensionHoverWidget,
142140
this.instantiationService.createInstance(SyncIgnoredWidget, syncIgnore),
@@ -151,7 +149,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
151149
const disposable = combinedDisposable(...actions, ...widgets, actionbar, actionBarListener, extensionContainers);
152150

153151
return {
154-
root, element, icon, name, installCount, ratings, description, disposables: [disposable], actionbar,
152+
root, element, name, installCount, ratings, description, disposables: [disposable], actionbar,
155153
extensionDisposables: [],
156154
set extension(extension: IExtension) {
157155
extensionContainers.extension = extension;
@@ -165,7 +163,6 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
165163
data.root.removeAttribute('aria-label');
166164
data.root.removeAttribute('data-extension-id');
167165
data.extensionDisposables = dispose(data.extensionDisposables);
168-
data.icon.src = '';
169166
data.name.textContent = '';
170167
data.description.textContent = '';
171168
data.installCount.style.display = 'none';
@@ -193,16 +190,6 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
193190
updateEnablement();
194191
this.extensionService.onDidChangeExtensions(() => updateEnablement(), this, data.extensionDisposables);
195192

196-
data.extensionDisposables.push(addDisposableListener(data.icon, 'error', () => data.icon.src = extension.iconUrlFallback, { once: true }));
197-
data.icon.src = extension.iconUrl;
198-
199-
if (!data.icon.complete) {
200-
data.icon.style.visibility = 'hidden';
201-
data.icon.onload = () => data.icon.style.visibility = 'inherit';
202-
} else {
203-
data.icon.style.visibility = 'inherit';
204-
}
205-
206193
data.name.textContent = extension.displayName;
207194
data.description.textContent = extension.description;
208195

src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { IContextMenuService } from '../../../../platform/contextview/browser/co
3535
import { INotificationService } from '../../../../platform/notification/common/notification.js';
3636
import { getLocationBasedViewColors } from '../../../browser/parts/views/viewPane.js';
3737
import { DelayedPagedModel, IPagedModel } from '../../../../base/common/paging.js';
38+
import { ExtensionIconWidget } from './extensionsWidgets.js';
3839

3940
export class ExtensionsList extends Disposable {
4041

@@ -201,7 +202,6 @@ export class ExtensionsGridView extends Disposable {
201202
}
202203

203204
interface IExtensionTemplateData {
204-
icon: HTMLImageElement;
205205
name: HTMLElement;
206206
identifier: HTMLElement;
207207
author: HTMLElement;
@@ -257,6 +257,7 @@ class ExtensionRenderer implements IListRenderer<ITreeNode<IExtensionData>, IExt
257257
container.classList.add('extension');
258258

259259
const icon = dom.append(container, dom.$<HTMLImageElement>('img.icon'));
260+
const iconWidget = this.instantiationService.createInstance(ExtensionIconWidget, icon);
260261
const details = dom.append(container, dom.$('.details'));
261262

262263
const header = dom.append(details, dom.$('.header'));
@@ -266,35 +267,25 @@ class ExtensionRenderer implements IListRenderer<ITreeNode<IExtensionData>, IExt
266267
openExtensionAction.run(e.ctrlKey || e.metaKey);
267268
e.stopPropagation();
268269
e.preventDefault();
269-
})];
270+
}), iconWidget, openExtensionAction];
270271
const identifier = dom.append(header, dom.$('span.identifier'));
271272

272273
const footer = dom.append(details, dom.$('.footer'));
273274
const author = dom.append(footer, dom.$('.author'));
274275
return {
275-
icon,
276276
name,
277277
identifier,
278278
author,
279279
extensionDisposables,
280280
set extensionData(extensionData: IExtensionData) {
281+
iconWidget.extension = extensionData.extension;
281282
openExtensionAction.extension = extensionData.extension;
282283
}
283284
};
284285
}
285286

286287
public renderElement(node: ITreeNode<IExtensionData>, index: number, data: IExtensionTemplateData): void {
287288
const extension = node.element.extension;
288-
data.extensionDisposables.push(dom.addDisposableListener(data.icon, 'error', () => data.icon.src = extension.iconUrlFallback, { once: true }));
289-
data.icon.src = extension.iconUrl;
290-
291-
if (!data.icon.complete) {
292-
data.icon.style.visibility = 'hidden';
293-
data.icon.onload = () => data.icon.style.visibility = 'inherit';
294-
} else {
295-
data.icon.style.visibility = 'inherit';
296-
}
297-
298289
data.name.textContent = extension.displayName;
299290
data.identifier.textContent = extension.identifier.id;
300291
data.author.textContent = extension.publisherDisplayName;

0 commit comments

Comments
 (0)