Skip to content

Commit

Permalink
Fix #68408
Browse files Browse the repository at this point in the history
  • Loading branch information
sandy081 committed Feb 11, 2019
1 parent ebf55c1 commit dbce60b
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets';
import { EditorOptions } from 'vs/workbench/common/editor';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
Expand Down Expand Up @@ -367,6 +367,8 @@ export class ExtensionEditor extends BaseEditor {
reloadAction,
this.instantiationService.createInstance(StatusLabelAction),
this.instantiationService.createInstance(UpdateAction),
this.instantiationService.createInstance(SetColorThemeAction),
this.instantiationService.createInstance(SetFileIconThemeAction),
this.instantiationService.createInstance(EnableDropDownAction),
this.instantiationService.createInstance(DisableDropDownAction, runningExtensions),
this.instantiationService.createInstance(CombinedInstallAction),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import { clipboard } from 'electron';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { coalesce } from 'vs/base/common/arrays';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IWorkbenchThemeService, COLOR_THEME_SETTING } from 'vs/workbench/services/themes/common/workbenchThemeService';

function toExtensionDescription(local: ILocalExtension): IExtensionDescription {
return {
Expand Down Expand Up @@ -147,7 +147,6 @@ export class InstallAction extends ExtensionAction {
@IInstantiationService private readonly instantiationService: IInstantiationService,
@INotificationService private readonly notificationService: INotificationService,
@IOpenerService private readonly openerService: IOpenerService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IExtensionService private readonly runtimeExtensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService
) {
Expand Down Expand Up @@ -183,8 +182,22 @@ export class InstallAction extends ExtensionAction {

const extension = await this.install(this.extension);

if (extension.local && extension.local.manifest.contributes && extension.local.manifest.contributes.themes && extension.local.manifest.contributes.themes.length) {
return this.applyInstalledTheme(extension.local);
if (extension.local) {
const runningExtension = await this.getRunningExtension(extension.local);
if (runningExtension) {
const colorThemes = await this.workbenchThemeService.getColorThemes(runningExtension.identifier);
const fileIconThemes = await this.workbenchThemeService.getFileIconThemes(runningExtension.identifier);
if (colorThemes.length && !fileIconThemes.length) {
const action = this.instantiationService.createInstance(SetColorThemeAction);
action.extension = extension;
return action.run(true);
}
if (!colorThemes.length && fileIconThemes.length) {
const action = this.instantiationService.createInstance(SetFileIconThemeAction);
action.extension = extension;
return action.run(true);
}
}
}

}
Expand All @@ -202,25 +215,6 @@ export class InstallAction extends ExtensionAction {
});
}

private async applyInstalledTheme(extension: ILocalExtension): Promise<void> {
const runningExtension = await this.getRunningExtension(extension);
if (runningExtension) {
const currentTheme = this.workbenchThemeService.getColorTheme();
const themes = await this.workbenchThemeService.getColorThemes(runningExtension.identifier);
const delayer = new Delayer<void>(100);
const picks: (IQuickPickItem | IQuickPickSeparator)[] = themes.map(theme => (<IQuickPickItem>{ label: theme.label, id: theme.id }));
picks.push(<IQuickPickSeparator>{ type: 'separator' });
picks.push(<IQuickPickItem>{ label: localize('stay with current theme', "Stay with current theme ({0})", currentTheme.label), id: currentTheme.id });
const pickedTheme = await this.quickInputService.pick(
picks,
{
placeHolder: localize('apply installed theme', "Apply installed theme or press Escape to cancel."),
onDidFocus: item => delayer.trigger(() => this.workbenchThemeService.setColorTheme(item.id, ConfigurationTarget.MEMORY).then(() => undefined))
});
this.workbenchThemeService.setColorTheme(pickedTheme ? pickedTheme.id : currentTheme.id, undefined);
}
}

private async getRunningExtension(extension: ILocalExtension): Promise<IExtensionDescription | null> {
const runningExtension = await this.runtimeExtensionService.getExtension(extension.identifier.id);
if (runningExtension) {
Expand Down Expand Up @@ -1111,6 +1105,138 @@ export class ReloadAction extends ExtensionAction {
}
}

export class SetColorThemeAction extends ExtensionAction {

private static readonly EnabledClass = 'extension-action theme';
private static readonly DisabledClass = `${SetColorThemeAction.EnabledClass} disabled`;

private disposables: IDisposable[] = [];

constructor(
@IExtensionService extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super(`extensions.colorTheme`, localize('color theme', "Set Color Theme"), SetColorThemeAction.DisabledClass, false);
Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidColorThemeChange)(() => this.update(), this, this.disposables);
this.update();
}

async update(): Promise<void> {
this.enabled = false;
if (this.extension) {
const isInstalled = this.extension.state === ExtensionState.Installed;
if (isInstalled) {
const colorThemes = await this.workbenchThemeService.getColorThemes(new ExtensionIdentifier(this.extension.identifier.id));
this.enabled = colorThemes.length > 0;
}
}
this.class = this.enabled ? SetColorThemeAction.EnabledClass : SetColorThemeAction.DisabledClass;
}

async run(showCurrentTheme: boolean): Promise<any> {
await this.update();
if (!this.enabled) {
return;
}
let colorThemes = await this.workbenchThemeService.getColorThemes(new ExtensionIdentifier(this.extension.identifier.id));
const currentTheme = this.workbenchThemeService.getColorTheme();
showCurrentTheme = showCurrentTheme || colorThemes.some(t => t.id === currentTheme.id);
if (showCurrentTheme) {
colorThemes = colorThemes.filter(t => t.id !== currentTheme.id);
}

const delayer = new Delayer<any>(100);
const picks: (IQuickPickItem | IQuickPickSeparator)[] = [];
picks.push(...colorThemes.map(theme => (<IQuickPickItem>{ label: theme.label, id: theme.id })));
if (showCurrentTheme) {
picks.push(<IQuickPickSeparator>{ type: 'separator', label: localize('current', "Current") });
picks.push(<IQuickPickItem>{ label: currentTheme.label, id: currentTheme.id });
}
const pickedTheme = await this.quickInputService.pick(
picks,
{
placeHolder: localize('select color theme', "Select Color Theme"),
onDidFocus: item => delayer.trigger(() => this.workbenchThemeService.setColorTheme(item.id, undefined))
});
let confValue = this.configurationService.inspect(COLOR_THEME_SETTING);
const target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER;
return this.workbenchThemeService.setColorTheme(pickedTheme ? pickedTheme.id : currentTheme.id, target);
}

dispose() {
this.disposables = dispose(this.disposables);
super.dispose();
}
}

export class SetFileIconThemeAction extends ExtensionAction {

private static readonly EnabledClass = 'extension-action theme';
private static readonly DisabledClass = `${SetFileIconThemeAction.EnabledClass} disabled`;

private disposables: IDisposable[] = [];

constructor(
@IExtensionService extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super(`extensions.fileIconTheme`, localize('file icon theme', "Set File Icon Theme"), SetFileIconThemeAction.DisabledClass, false);
Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidFileIconThemeChange)(() => this.update(), this, this.disposables);
this.update();
}

async update(): Promise<void> {
this.enabled = false;
if (this.extension) {
const isInstalled = this.extension.state === ExtensionState.Installed;
if (isInstalled) {
const fileIconThemes = await this.workbenchThemeService.getFileIconThemes(new ExtensionIdentifier(this.extension.identifier.id));
this.enabled = fileIconThemes.length > 0;
}
}
this.class = this.enabled ? SetFileIconThemeAction.EnabledClass : SetFileIconThemeAction.DisabledClass;
}

async run(showCurrentTheme: boolean): Promise<any> {
await this.update();
if (!this.enabled) {
return;
}
let fileIconThemes = await this.workbenchThemeService.getFileIconThemes(new ExtensionIdentifier(this.extension.identifier.id));
const currentTheme = this.workbenchThemeService.getFileIconTheme();
showCurrentTheme = showCurrentTheme || fileIconThemes.some(t => t.id === currentTheme.id);
if (showCurrentTheme) {
fileIconThemes = fileIconThemes.filter(t => t.id !== currentTheme.id);
}

const delayer = new Delayer<any>(100);
const picks: (IQuickPickItem | IQuickPickSeparator)[] = [];
picks.push(...fileIconThemes.map(theme => (<IQuickPickItem>{ label: theme.label, id: theme.id })));
if (showCurrentTheme) {
picks.push(<IQuickPickSeparator>{ type: 'separator', label: localize('current', "Current") });
picks.push(<IQuickPickItem>{ label: currentTheme.label, id: currentTheme.id });
}
const pickedTheme = await this.quickInputService.pick(
picks,
{
placeHolder: localize('select file icon theme', "Select File Icon Theme"),
onDidFocus: item => delayer.trigger(() => this.workbenchThemeService.setFileIconTheme(item.id, undefined))
});
let confValue = this.configurationService.inspect(COLOR_THEME_SETTING);
const target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER;
return this.workbenchThemeService.setFileIconTheme(pickedTheme ? pickedTheme.id : currentTheme.id, target);
}

dispose() {
this.disposables = dispose(this.disposables);
super.dispose();
}
}

export class OpenExtensionsViewletAction extends ShowViewletAction {

static ID = VIEWLET_ID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
.monaco-action-bar .action-item.disabled .action-label.extension-action.install:not(.installing),
.monaco-action-bar .action-item.disabled .action-label.extension-action.uninstall:not(.uninstalling),
.monaco-action-bar .action-item.disabled .action-label.extension-action.update,
.monaco-action-bar .action-item.disabled .action-label.extension-action.theme,
.monaco-action-bar .action-item.disabled .action-label.extension-action.extension-editor-dropdown-action,
.monaco-action-bar .action-item.disabled .action-label.extension-action.reload,
.monaco-action-bar .action-item.disabled .action-label.disable-status.hide,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export interface IWorkbenchThemeService extends IThemeService {

setFileIconTheme(iconThemeId: string | undefined, settingsTarget: ConfigurationTarget | undefined): Promise<IFileIconTheme>;
getFileIconTheme(): IFileIconTheme;
getFileIconThemes(): Promise<IFileIconTheme[]>;
getFileIconThemes(extensionId?: ExtensionIdentifier): Promise<IFileIconTheme[]>;
onDidFileIconThemeChange: Event<IFileIconTheme>;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,9 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
}
}

public getFileIconThemes(): Promise<IFileIconTheme[]> {
return this.iconThemeStore.getFileIconThemes();
public async getFileIconThemes(extensionId?: ExtensionIdentifier): Promise<IFileIconTheme[]> {
const filIconThemes = await this.iconThemeStore.getFileIconThemes();
return extensionId ? filIconThemes.filter(c => c.extensionData && ExtensionIdentifier.equals(new ExtensionIdentifier(c.extensionData.extensionId), extensionId)) : filIconThemes;
}

public getFileIconTheme() {
Expand Down

0 comments on commit dbce60b

Please sign in to comment.