diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index 2119f146186..aa2fc7bb015 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -307,7 +307,7 @@ class MarketplaceThemes { const ext = gallery[i]; if (!installedExtensions.has(ext.identifier.id) && !this._marketplaceExtensions.has(ext.identifier.id)) { this._marketplaceExtensions.add(ext.identifier.id); - const themes = await this.themeService.getMarketplaceColorThemes(ext.identifier.id, ext.version); + const themes = await this.themeService.getMarketplaceColorThemes(ext.publisher, ext.name, ext.version); for (const theme of themes) { this._marketplaceThemes.push({ id: theme.id, theme: theme, label: theme.label, description: `${ext.displayName} ยท ${ext.publisherDisplayName}`, galleryExtension: ext, buttons: [configureButton] }); } diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index 21e03d8f81a..09ef85d453a 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -407,21 +407,15 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { return this.colorThemeRegistry.getThemes(); } - public async getMarketplaceColorThemes(id: string, version: string): Promise { - const [publisher, name] = id.split('.'); + public async getMarketplaceColorThemes(publisher: string, name: string, version: string): Promise { const extensionLocation = this.extensionResourceLoaderService.getExtensionGalleryResourceURL({ publisher, name, version }, 'extension'); - if (!extensionLocation) { - return []; - } - try { - const manifestContent = await this.extensionResourceLoaderService.readExtensionResource(resources.joinPath(extensionLocation, 'package.json')); - - const data: ExtensionData = { extensionPublisher: publisher, extensionId: id, extensionName: name, extensionIsBuiltin: false }; - - return this.colorThemeRegistry.getMarketplaceThemes(JSON.parse(manifestContent), extensionLocation, data); - - } catch (e) { - this.logService.error(`Problem loading themes from marketplace ${e}`); + if (extensionLocation) { + try { + const manifestContent = await this.extensionResourceLoaderService.readExtensionResource(resources.joinPath(extensionLocation, 'package.json')); + return this.colorThemeRegistry.getMarketplaceThemes(JSON.parse(manifestContent), extensionLocation, ExtensionData.fromName(publisher, name)); + } catch (e) { + this.logService.error('Problem loading themes from marketplace', e); + } } return []; } @@ -593,13 +587,21 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { return this.onFileIconThemeChange.event; } - - public async setFileIconTheme(iconTheme: string | undefined, settingsTarget: ThemeSettingTarget): Promise { + public async setFileIconTheme(iconThemeOrId: string | undefined | IWorkbenchFileIconTheme, settingsTarget: ThemeSettingTarget): Promise { return this.fileIconThemeSequencer.queue(async () => { - iconTheme = iconTheme || ''; - if (iconTheme !== this.currentFileIconTheme.id || !this.currentFileIconTheme.isLoaded) { + if (iconThemeOrId === undefined) { + iconThemeOrId = ''; + } + const themeId = types.isString(iconThemeOrId) ? iconThemeOrId : iconThemeOrId.id; + if (themeId !== this.currentFileIconTheme.id || !this.currentFileIconTheme.isLoaded) { - const newThemeData = this.fileIconThemeRegistry.findThemeById(iconTheme) || FileIconThemeData.noIconTheme; + let newThemeData = this.fileIconThemeRegistry.findThemeById(themeId); + if (!newThemeData && iconThemeOrId instanceof FileIconThemeData) { + newThemeData = iconThemeOrId; + } + if (!newThemeData) { + newThemeData = FileIconThemeData.noIconTheme; + } await newThemeData.ensureLoaded(this.extensionResourceLoaderService); this.applyAndSetFileIconTheme(newThemeData); // updates this.currentFileIconTheme @@ -617,6 +619,19 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { }); } + public async getMarketplaceFileIconThemes(publisher: string, name: string, version: string): Promise { + const extensionLocation = this.extensionResourceLoaderService.getExtensionGalleryResourceURL({ publisher, name, version }, 'extension'); + if (extensionLocation) { + try { + const manifestContent = await this.extensionResourceLoaderService.readExtensionResource(resources.joinPath(extensionLocation, 'package.json')); + return this.fileIconThemeRegistry.getMarketplaceThemes(JSON.parse(manifestContent), extensionLocation, ExtensionData.fromName(publisher, name)); + } catch (e) { + this.logService.error('Problem loading themes from marketplace', e); + } + } + return []; + } + private async reloadCurrentFileIconTheme() { return this.fileIconThemeSequencer.queue(async () => { await this.currentFileIconTheme.reload(this.extensionResourceLoaderService); @@ -625,15 +640,19 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { } public async restoreFileIconTheme(): Promise { - const settingId = this.settings.fileIconTheme; - const theme = this.fileIconThemeRegistry.findThemeBySettingsId(settingId); - if (theme) { - if (settingId !== this.currentFileIconTheme.settingsId) { - await this.setFileIconTheme(theme.id, undefined); + return this.fileIconThemeSequencer.queue(async () => { + const settingId = this.settings.fileIconTheme; + const theme = this.fileIconThemeRegistry.findThemeBySettingsId(settingId); + if (theme) { + if (settingId !== this.currentFileIconTheme.settingsId) { + await this.setFileIconTheme(theme.id, undefined); + } else if (theme !== this.currentFileIconTheme) { + this.applyAndSetFileIconTheme(theme, true); + } + return true; } - return true; - } - return false; + return false; + }); } private applyAndSetFileIconTheme(iconThemeData: FileIconThemeData, silent = false): void { @@ -670,11 +689,20 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { return this.onProductIconThemeChange.event; } - public async setProductIconTheme(iconTheme: string | undefined, settingsTarget: ThemeSettingTarget): Promise { + public async setProductIconTheme(iconThemeOrId: string | undefined | IWorkbenchProductIconTheme, settingsTarget: ThemeSettingTarget): Promise { return this.productIconThemeSequencer.queue(async () => { - iconTheme = iconTheme || ''; - if (iconTheme !== this.currentProductIconTheme.id || !this.currentProductIconTheme.isLoaded) { - const newThemeData = this.productIconThemeRegistry.findThemeById(iconTheme) || ProductIconThemeData.defaultTheme; + if (iconThemeOrId === undefined) { + iconThemeOrId = ''; + } + const themeId = types.isString(iconThemeOrId) ? iconThemeOrId : iconThemeOrId.id; + if (themeId !== this.currentProductIconTheme.id || !this.currentProductIconTheme.isLoaded) { + let newThemeData = this.productIconThemeRegistry.findThemeById(themeId); + if (!newThemeData && iconThemeOrId instanceof ProductIconThemeData) { + newThemeData = iconThemeOrId; + } + if (!newThemeData) { + newThemeData = ProductIconThemeData.defaultTheme; + } await newThemeData.ensureLoaded(this.extensionResourceLoaderService, this.logService); this.applyAndSetProductIconTheme(newThemeData); // updates this.currentProductIconTheme @@ -691,6 +719,19 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { }); } + public async getMarketplaceProductIconThemes(publisher: string, name: string, version: string): Promise { + const extensionLocation = this.extensionResourceLoaderService.getExtensionGalleryResourceURL({ publisher, name, version }, 'extension'); + if (extensionLocation) { + try { + const manifestContent = await this.extensionResourceLoaderService.readExtensionResource(resources.joinPath(extensionLocation, 'package.json')); + return this.productIconThemeRegistry.getMarketplaceThemes(JSON.parse(manifestContent), extensionLocation, ExtensionData.fromName(publisher, name)); + } catch (e) { + this.logService.error('Problem loading themes from marketplace', e); + } + } + return []; + } + private async reloadCurrentProductIconTheme() { return this.productIconThemeSequencer.queue(async () => { await this.currentProductIconTheme.reload(this.extensionResourceLoaderService, this.logService); @@ -699,15 +740,19 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { } public async restoreProductIconTheme(): Promise { - const settingId = this.settings.productIconTheme; - const theme = this.productIconThemeRegistry.findThemeBySettingsId(settingId); - if (theme) { - if (settingId !== this.currentProductIconTheme.settingsId) { - await this.setProductIconTheme(theme.id, undefined); + return this.productIconThemeSequencer.queue(async () => { + const settingId = this.settings.productIconTheme; + const theme = this.productIconThemeRegistry.findThemeBySettingsId(settingId); + if (theme) { + if (settingId !== this.currentProductIconTheme.settingsId) { + await this.setProductIconTheme(theme.id, undefined); + } else if (theme !== this.currentProductIconTheme) { + this.applyAndSetProductIconTheme(theme, true); + } + return true; } - return true; - } - return false; + return false; + }); } private applyAndSetProductIconTheme(iconThemeData: ProductIconThemeData, silent = false): void { diff --git a/src/vs/workbench/services/themes/common/themeExtensionPoints.ts b/src/vs/workbench/services/themes/common/themeExtensionPoints.ts index ae8ae9701ff..5382bea8499 100644 --- a/src/vs/workbench/services/themes/common/themeExtensionPoints.ts +++ b/src/vs/workbench/services/themes/common/themeExtensionPoints.ts @@ -141,13 +141,8 @@ export class ThemeRegistry { previousIds[theme.id] = theme; } this.extensionThemes.length = 0; - for (let ext of extensions) { - let extensionData: ExtensionData = { - extensionId: ext.description.identifier.value, - extensionPublisher: ext.description.publisher, - extensionName: ext.description.name, - extensionIsBuiltin: ext.description.isBuiltin - }; + for (const ext of extensions) { + const extensionData = ExtensionData.fromName(ext.description.publisher, ext.description.name, ext.description.isBuiltin); this.onThemes(extensionData, ext.description.extensionLocation, ext.value, this.extensionThemes, ext.collector); } for (const theme of this.extensionThemes) { diff --git a/src/vs/workbench/services/themes/common/workbenchThemeService.ts b/src/vs/workbench/services/themes/common/workbenchThemeService.ts index b575fbeb048..502d0fbd8a1 100644 --- a/src/vs/workbench/services/themes/common/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/common/workbenchThemeService.ts @@ -71,18 +71,19 @@ export interface IWorkbenchThemeService extends IThemeService { setColorTheme(themeId: string | undefined | IWorkbenchColorTheme, settingsTarget: ThemeSettingTarget): Promise; getColorTheme(): IWorkbenchColorTheme; getColorThemes(): Promise; - getMarketplaceColorThemes(id: string, version: string): Promise; + getMarketplaceColorThemes(publisher: string, name: string, version: string): Promise; onDidColorThemeChange: Event; - restoreColorTheme(): void; - setFileIconTheme(iconThemeId: string | undefined, settingsTarget: ThemeSettingTarget): Promise; + setFileIconTheme(iconThemeId: string | undefined | IWorkbenchFileIconTheme, settingsTarget: ThemeSettingTarget): Promise; getFileIconTheme(): IWorkbenchFileIconTheme; getFileIconThemes(): Promise; + getMarketplaceFileIconThemes(publisher: string, name: string, version: string): Promise; onDidFileIconThemeChange: Event; - setProductIconTheme(iconThemeId: string | undefined, settingsTarget: ThemeSettingTarget): Promise; + setProductIconTheme(iconThemeId: string | undefined | IWorkbenchProductIconTheme, settingsTarget: ThemeSettingTarget): Promise; getProductIconTheme(): IWorkbenchProductIconTheme; getProductIconThemes(): Promise; + getMarketplaceProductIconThemes(publisher: string, name: string, version: string): Promise; onDidProductIconThemeChange: Event; } @@ -199,6 +200,9 @@ export namespace ExtensionData { } return undefined; } + export function fromName(publisher: string, name: string, isBuiltin = false) : ExtensionData { + return { extensionPublisher: publisher, extensionId: `${publisher}.${name}`, extensionName: name, extensionIsBuiltin: isBuiltin }; + } } export interface IThemeExtensionPoint {