提交 f0dfae7c 编写于 作者: M Martin Aeschlimann

Cache a theme to apply it fast on startup instead of waiting for extensions. fixes #22137

上级 bb3c3f0b
...@@ -88,6 +88,23 @@ export class ColorThemeData implements IColorTheme { ...@@ -88,6 +88,23 @@ export class ColorThemeData implements IColorTheme {
return JSON.stringify(content, null, '\t'); return JSON.stringify(content, null, '\t');
} }
toStorageData() {
let colorMapData = {};
for (let key in this.colorMap) {
colorMapData[key] = this.colorMap[key].toRGBAHex(true);
}
return JSON.stringify({
id: this.id,
label: this.label,
settingsId: this.settingsId,
selector: this.selector,
tokenColors: this.tokenColors,
isLoaded: true,
extensionData: this.extensionData,
colorMap: colorMapData
});
}
get type(): ThemeType { get type(): ThemeType {
switch (this.getBaseThemeId()) { switch (this.getBaseThemeId()) {
case VS_LIGHT_THEME: return 'light'; case VS_LIGHT_THEME: return 'light';
...@@ -113,6 +130,22 @@ export class ColorThemeData implements IColorTheme { ...@@ -113,6 +130,22 @@ export class ColorThemeData implements IColorTheme {
} }
} }
export function fromStorageData(input: string): ColorThemeData {
let data = JSON.parse(input);
let theme = new ColorThemeData();
for (let key in data) {
if (key !== 'colorMap') {
theme[key] = data[key];
} else {
let colorMapData = data[key];
for (let id in colorMapData) {
theme.colorMap[id] = Color.fromHex(colorMapData[id]);
}
}
}
return theme;
}
let defaultThemeColors: { [baseTheme: string]: ITokenColorizationRule[] } = { let defaultThemeColors: { [baseTheme: string]: ITokenColorizationRule[] } = {
'vs': [ 'vs': [
{ scope: 'token.info-token', settings: { foreground: '#316bcd' } }, { scope: 'token.info-token', settings: { foreground: '#316bcd' } },
......
...@@ -26,8 +26,9 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment' ...@@ -26,8 +26,9 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { IMessageService } from 'vs/platform/message/common/message'; import { IMessageService } from 'vs/platform/message/common/message';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import Severity from 'vs/base/common/severity'; import Severity from 'vs/base/common/severity';
import { ColorThemeData } from './colorThemeData'; import { ColorThemeData, fromStorageData } from './colorThemeData';
import { ITheme, Extensions as ThemingExtensions, IThemingRegistry } from 'vs/platform/theme/common/themeService'; import { ITheme, Extensions as ThemingExtensions, IThemingRegistry } from 'vs/platform/theme/common/themeService';
import { editorBackground, editorForeground } from 'vs/platform/theme/common/colorRegistry';
import { $ } from 'vs/base/browser/builder'; import { $ } from 'vs/base/browser/builder';
import Event, { Emitter } from 'vs/base/common/event'; import Event, { Emitter } from 'vs/base/common/event';
...@@ -44,6 +45,8 @@ import { IDisposable } from 'vs/base/common/lifecycle'; ...@@ -44,6 +45,8 @@ import { IDisposable } from 'vs/base/common/lifecycle';
const DEFAULT_THEME_ID = 'vs-dark vscode-theme-defaults-themes-dark_plus-json'; const DEFAULT_THEME_ID = 'vs-dark vscode-theme-defaults-themes-dark_plus-json';
const DEFAULT_THEME_SETTING_VALUE = 'Default Dark+'; const DEFAULT_THEME_SETTING_VALUE = 'Default Dark+';
const PERSISTED_THEME_STORAGE_KEY = 'colorThemeData';
const defaultBaseTheme = 'vs-dark'; const defaultBaseTheme = 'vs-dark';
const defaultThemeExtensionId = 'vscode-theme-defaults'; const defaultThemeExtensionId = 'vscode-theme-defaults';
...@@ -202,13 +205,30 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { ...@@ -202,13 +205,30 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
this.container = container; this.container = container;
this.knownColorThemes = []; this.knownColorThemes = [];
this.onFileIconThemeChange = new Emitter<IFileIconTheme>();
this.knownIconThemes = [];
this.onColorThemeChange = new Emitter<IColorTheme>();
this.currentIconTheme = {
id: '',
label: '',
settingsId: null,
isLoaded: false,
hasFileIcons: false,
hasFolderIcons: false,
extensionData: null
};
let persistedThemeData = this.storageService.get(PERSISTED_THEME_STORAGE_KEY);
if (persistedThemeData) {
let themeData = fromStorageData(persistedThemeData);
this.updateDynamicCSSRules(themeData);
this.applyTheme(themeData, null, true);
} else {
// In order to avoid paint flashing for tokens, because // In order to avoid paint flashing for tokens, because
// themes are loaded asynchronously, we need to initialize // themes are loaded asynchronously, we need to initialize
// a color theme document with good defaults until the theme is loaded // a color theme document with good defaults until the theme is loaded
let isLightTheme = (Array.prototype.indexOf.call(document.body.classList, 'vs') >= 0); let isLightTheme = (Array.prototype.indexOf.call(document.body.classList, 'vs') >= 0);
let foreground = isLightTheme ? '#000000' : '#D4D4D4';
let background = isLightTheme ? '#ffffff' : '#1E1E1E';
let initialTheme = new ColorThemeData(); let initialTheme = new ColorThemeData();
initialTheme.id = isLightTheme ? VS_LIGHT_THEME : VS_DARK_THEME; initialTheme.id = isLightTheme ? VS_LIGHT_THEME : VS_DARK_THEME;
...@@ -218,24 +238,12 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { ...@@ -218,24 +238,12 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
initialTheme.isLoaded = false; initialTheme.isLoaded = false;
initialTheme.tokenColors = [{ initialTheme.tokenColors = [{
settings: { settings: {
foreground: foreground, foreground: initialTheme.getColor(editorForeground).toRGBAHex(),
background: background background: initialTheme.getColor(editorBackground).toRGBAHex()
} }
}]; }];
this.currentColorTheme = initialTheme; this.currentColorTheme = initialTheme;
}
this.onColorThemeChange = new Emitter<IColorTheme>();
this.knownIconThemes = [];
this.currentIconTheme = {
id: '',
label: '',
settingsId: null,
isLoaded: false,
hasFileIcons: false,
hasFolderIcons: false,
extensionData: null
};
this.onFileIconThemeChange = new Emitter<IFileIconTheme>();
themesExtPoint.setHandler((extensions) => { themesExtPoint.setHandler((extensions) => {
for (let ext of extensions) { for (let ext of extensions) {
...@@ -381,33 +389,11 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { ...@@ -381,33 +389,11 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
this.themingParticipantChangeListener = null; this.themingParticipantChangeListener = null;
} }
let onApply = (newTheme: ColorThemeData) => {
let newThemeId = newTheme.id;
if (this.container) {
if (this.currentColorTheme) {
$(this.container).removeClass(this.currentColorTheme.id);
}
$(this.container).addClass(newThemeId);
}
this.currentColorTheme = newTheme;
this.themingParticipantChangeListener = themingRegistry.onThemingParticipantAdded(p => this.updateDynamicCSSRules(this.currentColorTheme));
this.sendTelemetry(newTheme.id, newTheme.extensionData, 'color');
this.onColorThemeChange.fire(this.currentColorTheme);
if (settingsTarget !== ConfigurationTarget.WORKSPACE) {
this.windowService.broadcast({ channel: 'vscode:changeColorTheme', payload: newTheme.id });
}
return this.writeColorThemeConfiguration(settingsTarget);
};
return this.findThemeData(themeId, DEFAULT_THEME_ID).then(themeData => { return this.findThemeData(themeId, DEFAULT_THEME_ID).then(themeData => {
if (themeData) { if (themeData) {
return themeData.ensureLoaded().then(_ => { return themeData.ensureLoaded().then(_ => {
this.updateDynamicCSSRules(themeData); this.updateDynamicCSSRules(themeData);
return onApply(themeData); return this.applyTheme(themeData, settingsTarget);
}, error => { }, error => {
return TPromise.wrapError(nls.localize('error.cannotloadtheme', "Unable to load {0}: {1}", themeData.path, error.message)); return TPromise.wrapError(nls.localize('error.cannotloadtheme', "Unable to load {0}: {1}", themeData.path, error.message));
}); });
...@@ -431,6 +417,33 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { ...@@ -431,6 +417,33 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
_applyRules(cssRules.join('\n'), colorThemeRulesClassName); _applyRules(cssRules.join('\n'), colorThemeRulesClassName);
} }
private applyTheme(newTheme: ColorThemeData, settingsTarget: ConfigurationTarget, silent = false): TPromise<IFileIconTheme> {
if (this.container) {
if (this.currentColorTheme) {
$(this.container).removeClass(this.currentColorTheme.id);
}
$(this.container).addClass(newTheme.id);
}
this.currentColorTheme = newTheme;
this.themingParticipantChangeListener = themingRegistry.onThemingParticipantAdded(p => this.updateDynamicCSSRules(this.currentColorTheme));
if (silent) {
return TPromise.as(null);
}
this.sendTelemetry(newTheme.id, newTheme.extensionData, 'color');
this.onColorThemeChange.fire(this.currentColorTheme);
if (settingsTarget !== ConfigurationTarget.WORKSPACE) {
this.windowService.broadcast({ channel: 'vscode:changeColorTheme', payload: newTheme.id });
}
// remember theme data for a quick restore
this.storageService.store(PERSISTED_THEME_STORAGE_KEY, newTheme.toStorageData());
return this.writeColorThemeConfiguration(settingsTarget);
};
private writeColorThemeConfiguration(settingsTarget: ConfigurationTarget): TPromise<IFileIconTheme> { private writeColorThemeConfiguration(settingsTarget: ConfigurationTarget): TPromise<IFileIconTheme> {
if (!types.isUndefinedOrNull(settingsTarget)) { if (!types.isUndefinedOrNull(settingsTarget)) {
return this.configurationWriter.writeConfiguration(COLOR_THEME_SETTING, this.currentColorTheme.settingsId, settingsTarget).then(_ => this.currentColorTheme); return this.configurationWriter.writeConfiguration(COLOR_THEME_SETTING, this.currentColorTheme.settingsId, settingsTarget).then(_ => this.currentColorTheme);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册