From 4f22d44706dc130e42f02b661bda3ca6bb463595 Mon Sep 17 00:00:00 2001 From: Joao Moreno Date: Tue, 23 Aug 2016 11:08:17 +0200 Subject: [PATCH] galleryExtension.iconUrlFallback related to #10180 --- .../common/extensionManagement.ts | 1 + .../node/extensionGalleryService.ts | 16 +++++++++++- .../electron-browser/extensionEditor.ts | 11 +++++--- .../extensions/electron-browser/extensions.ts | 1 + .../electron-browser/extensionsList.ts | 11 ++++++++ .../extensionsWorkbenchService.ts | 25 ++++++++++++++++--- .../media/extensionEditor.css | 5 +--- 7 files changed, 58 insertions(+), 12 deletions(-) diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 3163de80013..59decd945aa 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -33,6 +33,7 @@ export interface IGalleryExtensionAssets { readme: string; download: string; icon: string; + iconFallback: string; license: string; } diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts index 88d91604caa..3c56accf3b0 100644 --- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -181,11 +181,25 @@ function getAssetSource(files: IRawGalleryExtensionFile[], type: string): string function toExtension(galleryExtension: IRawGalleryExtension, extensionsGalleryUrl: string, downloadHeaders: { [key: string]: string; }): IGalleryExtension { const [version] = galleryExtension.versions; + + let iconFallback = getAssetSource(version.files, AssetType.Icon); + let icon: string; + + if (iconFallback) { + const parsedUrl = url.parse(iconFallback, true); + parsedUrl.search = undefined; + parsedUrl.query['redirect'] = 'true'; + icon = url.format(parsedUrl); + } else { + iconFallback = icon = require.toUrl('./media/defaultIcon.png'); + } + const assets = { manifest: getAssetSource(version.files, AssetType.Manifest), readme: getAssetSource(version.files, AssetType.Details), download: `${ getAssetSource(version.files, AssetType.VSIX) }?install=true`, - icon: getAssetSource(version.files, AssetType.Icon) || require.toUrl('./media/defaultIcon.png'), + icon, + iconFallback, license: getAssetSource(version.files, AssetType.License) }; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts index 97383961901..a8c49aa372e 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts @@ -12,6 +12,8 @@ import { marked } from 'vs/base/common/marked/marked'; import { onUnexpectedError } from 'vs/base/common/errors'; import { IDisposable, empty, dispose, toDisposable } from 'vs/base/common/lifecycle'; import { Builder } from 'vs/base/browser/builder'; +import { once } from 'vs/base/common/event'; +import { domEvent } from 'vs/base/browser/event'; import { append, emmet as $, addClass, removeClass, finalHandler } from 'vs/base/browser/dom'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { IViewlet } from 'vs/workbench/common/viewlet'; @@ -48,7 +50,7 @@ export class ExtensionEditor extends BaseEditor { static ID: string = 'workbench.editor.extension'; - private icon: HTMLElement; + private icon: HTMLImageElement; private name: HTMLAnchorElement; private license: HTMLAnchorElement; private publisher: HTMLAnchorElement; @@ -88,7 +90,7 @@ export class ExtensionEditor extends BaseEditor { const root = append(container, $('.extension-editor')); const header = append(root, $('.header')); - this.icon = append(header, $('.icon')); + this.icon = append(header, $('img.icon')); const details = append(header, $('.details')); const title = append(details, $('.title')); @@ -124,7 +126,10 @@ export class ExtensionEditor extends BaseEditor { const extension = input.extension; this.telemetryService.publicLog('extensionGallery:openExtension', extension.telemetryData); - this.icon.style.backgroundImage = `url("${ extension.iconUrl }")`; + const onError = once(domEvent(this.icon, 'error')); + onError(() => this.icon.src = extension.iconUrlFallback, null, this.transientDisposables); + this.icon.src = extension.iconUrl; + this.name.textContent = extension.displayName; this.publisher.textContent = extension.publisherDisplayName; this.description.textContent = extension.description; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensions.ts index 7ddb3aaef9a..f301a550410 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensions.ts @@ -34,6 +34,7 @@ export interface IExtension { description: string; readmeUrl: string; iconUrl: string; + iconUrlFallback: string; licenseUrl: string; installCount: number; rating: number; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsList.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsList.ts index 522a4c4c39e..dc912afa9e0 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsList.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsList.ts @@ -12,6 +12,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IMessageService, Severity } from 'vs/platform/message/common/message'; import { IDelegate } from 'vs/base/browser/ui/list/list'; import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging'; +import { once } from 'vs/base/common/event'; +import { domEvent } from 'vs/base/browser/event'; import { IExtension } from './extensions'; import { CombinedInstallAction, UpdateAction, EnableAction } from './extensionsActions'; import { Label, RatingsWidget, InstallWidget } from './extensionsWidgets'; @@ -27,6 +29,7 @@ export interface ITemplateData { description: HTMLElement; extension: IExtension; disposables: IDisposable[]; + extensionDisposables: IDisposable[]; } export class Delegate implements IDelegate { @@ -74,6 +77,7 @@ export class Renderer implements IPagedRenderer { return { element, icon, name, installCount, ratings, author, description, disposables, + extensionDisposables: [], set extension(extension: IExtension) { versionWidget.extension = extension; installCountWidget.extension = extension; @@ -87,6 +91,8 @@ export class Renderer implements IPagedRenderer { renderPlaceholder(index: number, data: ITemplateData): void { addClass(data.element, 'loading'); + + data.extensionDisposables = dispose(data.extensionDisposables); data.icon.src = ''; data.name.textContent = ''; data.author.textContent = ''; @@ -98,6 +104,11 @@ export class Renderer implements IPagedRenderer { renderElement(extension: IExtension, index: number, data: ITemplateData): void { removeClass(data.element, 'loading'); + + data.extensionDisposables = dispose(data.extensionDisposables); + + const onError = once(domEvent(data.icon, 'error')); + onError(() => data.icon.src = extension.iconUrlFallback, null, data.extensionDisposables); data.icon.src = extension.iconUrl; if (!data.icon.complete) { diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchService.ts index 39d1d045958..269b8a89cbe 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsWorkbenchService.ts @@ -86,11 +86,28 @@ class Extension implements IExtension { } get iconUrl(): string { - if (this.local && this.local.manifest.icon) { - return URI.file(path.join(this.local.path, this.local.manifest.icon)).toString(); - } + return this.localIconUrl || this.galleryIconUrl || this.defaultIconUrl; + } - return this.gallery ? this.gallery.assets.icon : require.toUrl('./media/defaultIcon.png'); + get iconUrlFallback(): string { + return this.localIconUrl || this.galleryIconUrlFallback || this.defaultIconUrl; + } + + private get localIconUrl(): string { + return this.local && this.local.manifest.icon + && URI.file(path.join(this.local.path, this.local.manifest.icon)).toString(); + } + + private get galleryIconUrl(): string { + return this.gallery && this.gallery.assets.icon; + } + + private get galleryIconUrlFallback(): string { + return this.gallery && this.gallery.assets.iconFallback; + } + + private get defaultIconUrl(): string { + return require.toUrl('./media/defaultIcon.png'); } get licenseUrl(): string { diff --git a/src/vs/workbench/parts/extensions/electron-browser/media/extensionEditor.css b/src/vs/workbench/parts/extensions/electron-browser/media/extensionEditor.css index 475d17659a6..683b31b5cbf 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/media/extensionEditor.css +++ b/src/vs/workbench/parts/extensions/electron-browser/media/extensionEditor.css @@ -24,10 +24,7 @@ .extension-editor > .header > .icon { height: 128px; width: 128px; - min-width: 128px; - background-size: 128px; - background-repeat: no-repeat; - background-position: center center; + object-fit: contain; } .extension-editor > .header > .details {