提交 494a6bcf 编写于 作者: M Martin Aeschlimann

polish

上级 9146c53f
......@@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import * as types from 'vs/base/common/types';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IWorkbenchThemeService, IColorTheme, ITokenColorCustomizations, IFileIconTheme, ExtensionData, VS_LIGHT_THEME, VS_DARK_THEME, VS_HC_THEME, COLOR_THEME_SETTING, ICON_THEME_SETTING, CUSTOM_WORKBENCH_COLORS_SETTING, CUSTOM_EDITOR_COLORS_SETTING, DETECT_HC_SETTING, HC_THEME_ID, IColorCustomizations, CUSTOM_EDITOR_TOKENSTYLES_SETTING, IExperimentalTokenStyleCustomizations, DETECT_AS_SETTING, COLOR_THEME_DARK_SETTING, COLOR_THEME_LIGHT_SETTING } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IWorkbenchThemeService, IColorTheme, ITokenColorCustomizations, IFileIconTheme, ExtensionData, VS_LIGHT_THEME, VS_DARK_THEME, VS_HC_THEME, COLOR_THEME_SETTING, ICON_THEME_SETTING, CUSTOM_WORKBENCH_COLORS_SETTING, CUSTOM_EDITOR_COLORS_SETTING, IColorCustomizations, CUSTOM_EDITOR_TOKENSTYLES_SETTING, IExperimentalTokenStyleCustomizations } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Registry } from 'vs/platform/registry/common/platform';
......@@ -14,7 +14,7 @@ import * as errors from 'vs/base/common/errors';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, IConfigurationPropertySchema, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry';
import { ColorThemeData } from 'vs/workbench/services/themes/common/colorThemeData';
import { ITheme, Extensions as ThemingExtensions, IThemingRegistry, DARK, LIGHT } from 'vs/platform/theme/common/themeService';
import { ITheme, Extensions as ThemingExtensions, IThemingRegistry, ThemeType, LIGHT, DARK, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
import { Event, Emitter } from 'vs/base/common/event';
import { registerFileIconThemeSchemas } from 'vs/workbench/services/themes/common/fileIconThemeSchema';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
......@@ -35,19 +35,21 @@ import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IExtensionResourceLoaderService } from 'vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader';
// settings
const PREFERRED_DARK_THEME_SETTING = 'workbench.preferredDarkColorTheme';
const PREFERRED_LIGHT_THEME_SETTING = 'workbench.preferredLightColorTheme';
const PREFERRED_HC_THEME_SETTING = 'workbench.preferredHighContrastColorTheme';
const DETECT_COLOR_SCHEME_SETTING = 'workbench.autoDetectColorScheme';
const DETECT_HC_SETTING = 'window.autoDetectHighContrast';
// implementation
const DEFAULT_THEME_ID = 'vs-dark vscode-theme-defaults-themes-dark_plus-json';
const DEFAULT_THEME_SETTING_VALUE = 'Default Dark+';
const DEFAULT_THEME_DARK_SETTING_VALUE = 'Default Dark+';
const DEFAULT_THEME_LIGHT_SETTING_VALUE = 'Default Light+';
const DEFAULT_THEME_AUTO_SWITCH_SETTING_VALUE = true;
enum ColorScheme {
LIGHT = 'light',
DARK = 'dark',
NO_PREFERENCE = 'no-preference'
}
const DEFAULT_THEME_HC_SETTING_VALUE = 'Default High Contrast';
const PERSISTED_THEME_STORAGE_KEY = 'colorThemeData';
const PERSISTED_ICON_THEME_STORAGE_KEY = 'iconThemeData';
......@@ -81,7 +83,6 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
private colorThemeStore: ColorThemeStore;
private currentColorTheme: ColorThemeData;
private autoSwitchColorTheme: MediaQueryList | undefined;
private container: HTMLElement;
private readonly onColorThemeChange: Emitter<IColorTheme>;
private watchedColorThemeLocation: URI | undefined;
......@@ -124,7 +125,6 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
this.iconThemeStore = new FileIconThemeStore(extensionService);
this.onColorThemeChange = new Emitter<IColorTheme>({ leakWarningThreshold: 400 });
this.onPreferColorSchemeChange = this.onPreferColorSchemeChange.bind(this);
this.currentColorTheme = ColorThemeData.createUnloadedTheme('');
this.currentIconTheme = FileIconThemeData.createUnloadedTheme('');
......@@ -159,7 +159,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
this.initialize().then(undefined, errors.onUnexpectedError).then(_ => {
this.installConfigurationListener();
this.installColorThemeSwitch();
this.installPreferredSchemeListener();
});
let prevColorId: string | undefined = undefined;
......@@ -260,76 +260,43 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
}
private initialize(): Promise<[IColorTheme | null, IFileIconTheme | null]> {
let colorThemeSetting = this.configurationService.getValue<string>(COLOR_THEME_SETTING);
let iconThemeSetting = this.configurationService.getValue<string | null>(ICON_THEME_SETTING);
let detectThemeAutoSwitch = this.configurationService.getValue<boolean>(DETECT_AS_SETTING);
if (detectThemeAutoSwitch) {
colorThemeSetting = this.getPreferredTheme();
}
let detectHCThemeSetting = this.configurationService.getValue<boolean>(DETECT_HC_SETTING);
if (this.environmentService.configuration.highContrast && detectHCThemeSetting) {
colorThemeSetting = HC_THEME_ID;
}
const colorThemeSetting = this.configurationService.getValue<string>(COLOR_THEME_SETTING);
const iconThemeSetting = this.configurationService.getValue<string | null>(ICON_THEME_SETTING);
const extDevLocs = this.environmentService.extensionDevelopmentLocationURI;
let uri: URI | undefined;
if (extDevLocs && extDevLocs.length > 0) {
// if there are more than one ext dev paths, use first
uri = extDevLocs[0];
}
return Promise.all([
this.colorThemeStore.findThemeDataBySettingsId(colorThemeSetting, DEFAULT_THEME_ID).then(theme => {
return this.colorThemeStore.findThemeDataByParentLocation(uri).then(devThemes => {
if (devThemes.length) {
return this.setColorTheme(devThemes[0].id, ConfigurationTarget.MEMORY);
} else {
return this.setColorTheme(theme && theme.id, undefined);
}
});
}),
this.iconThemeStore.findThemeBySettingsId(iconThemeSetting).then(theme => {
return this.iconThemeStore.findThemeDataByParentLocation(uri).then(devThemes => {
if (devThemes.length) {
return this.setFileIconTheme(devThemes[0].id, ConfigurationTarget.MEMORY);
} else {
return this.setFileIconTheme(theme ? theme.id : DEFAULT_ICON_THEME_ID, undefined);
}
});
}),
]);
}
private installColorThemeSwitch() {
console.log('INSTALL');
this.autoSwitchColorTheme = window.matchMedia('(prefers-color-scheme: dark)');
this.autoSwitchColorTheme.addListener(this.onPreferColorSchemeChange);
console.log('INSTALLED');
}
private deinstallColorThemeSwitch() {
console.log('DEINSTALL');
if (this.autoSwitchColorTheme) {
this.autoSwitchColorTheme.removeListener(this.onPreferColorSchemeChange);
this.configurationService.updateValue(DETECT_AS_SETTING, false);
console.log('DEINSTALLED');
}
}
const initializeColorTheme = async () => {
if (extDevLocs && extDevLocs.length > 0) { // in dev mode, switch to a theme provided by the extension under dev.
const devThemes = await this.colorThemeStore.findThemeDataByParentLocation(extDevLocs[0]);
if (devThemes.length) {
return this.setColorTheme(devThemes[0].id, ConfigurationTarget.MEMORY);
}
}
let theme = await this.colorThemeStore.findThemeDataBySettingsId(colorThemeSetting, DEFAULT_THEME_ID);
const preferredType = this.getPreferredColorScheme();
let settingsTarget: undefined | 'auto' = undefined;
if (preferredType && theme && theme.type !== preferredType) {
const preferedTheme = await this.getPreferredColorTheme(preferredType);
if (preferedTheme) {
theme = preferedTheme;
settingsTarget = 'auto';
}
}
return this.setColorTheme(theme && theme.id, settingsTarget);
};
private onPreferColorSchemeChange({ matches }: MediaQueryListEvent) {
console.log('onPreferColorSchemeChange', matches);
let colorThemeSetting = this.configurationService.getValue<string>(COLOR_THEME_LIGHT_SETTING);
if (matches) {
// prefers dark mode
colorThemeSetting = this.configurationService.getValue<string>(COLOR_THEME_DARK_SETTING);
}
this.colorThemeStore.findThemeDataBySettingsId(colorThemeSetting, DEFAULT_THEME_ID).then(theme => {
if (theme) {
this.setColorTheme(theme.id, undefined);
const initializeIconTheme = async () => {
if (extDevLocs && extDevLocs.length > 0) { // in dev mode, switch to a theme provided by the extension under dev.
const devThemes = await this.iconThemeStore.findThemeDataByParentLocation(extDevLocs[0]);
if (devThemes.length) {
return this.setFileIconTheme(devThemes[0].id, ConfigurationTarget.MEMORY);
}
}
});
const theme = await this.iconThemeStore.findThemeBySettingsId(iconThemeSetting);
return this.setFileIconTheme(theme ? theme.id : DEFAULT_ICON_THEME_ID, undefined);
};
return Promise.all([initializeColorTheme(), initializeIconTheme()]);
}
private installConfigurationListener() {
......@@ -339,31 +306,15 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
if (colorThemeSetting !== this.currentColorTheme.settingsId) {
this.colorThemeStore.findThemeDataBySettingsId(colorThemeSetting, DEFAULT_THEME_ID).then(theme => {
if (theme) {
if (this.autoSwitchColorTheme && theme.type === DARK) {
this.configurationService.updateValue(COLOR_THEME_DARK_SETTING, theme.settingsId);
}
if (this.autoSwitchColorTheme && theme.type === LIGHT) {
this.configurationService.updateValue(COLOR_THEME_LIGHT_SETTING, theme.settingsId);
}
this.setColorTheme(theme.id, undefined);
}
});
}
}
if (e.affectsConfiguration(DETECT_AS_SETTING)) {
let autoSwitchColorTheme = this.configurationService.getValue<boolean>(DETECT_AS_SETTING);
if (e.affectsConfiguration(DETECT_COLOR_SCHEME_SETTING)) {
let autoSwitchColorTheme = this.configurationService.getValue<boolean>(DETECT_COLOR_SCHEME_SETTING);
if (autoSwitchColorTheme) {
this.installColorThemeSwitch();
let colorThemeSetting = this.getPreferredTheme();
if (colorThemeSetting !== this.currentColorTheme.settingsId) {
this.colorThemeStore.findThemeDataBySettingsId(colorThemeSetting, DEFAULT_THEME_ID).then(theme => {
if (theme) {
this.setColorTheme(theme.id, undefined);
}
});
}
} else {
this.deinstallColorThemeSwitch();
this.preferredSchemeUpdated();
}
}
if (e.affectsConfiguration(ICON_THEME_SETTING)) {
......@@ -396,24 +347,45 @@ export class WorkbenchThemeService implements IWorkbenchThemeService {
});
}
private getPreferredTheme(): string {
let colorThemeSetting = this.configurationService.getValue<string>(COLOR_THEME_LIGHT_SETTING);
const darkMode = this.getPreferredColorScheme() === ColorScheme.DARK;
if (darkMode) {
colorThemeSetting = this.configurationService.getValue<string>(COLOR_THEME_DARK_SETTING);
// preferred scheme handling
private installPreferredSchemeListener() {
window.matchMedia('(prefers-color-scheme: dark)').addListener(async () => this.preferredSchemeUpdated());
}
private async preferredSchemeUpdated() {
const scheme = this.getPreferredColorScheme();
if (scheme && this.currentColorTheme.type !== scheme) {
const preferedTheme = await this.getPreferredColorTheme(scheme);
if (preferedTheme) {
return this.setColorTheme(preferedTheme.id, 'auto');
}
}
return colorThemeSetting;
return undefined;
}
public getPreferredColorScheme(): ColorScheme {
const noPreference = window.matchMedia(`(prefers-color-scheme: ${ColorScheme.NO_PREFERENCE})`).matches;
const prefersDark = window.matchMedia(`(prefers-color-scheme: ${ColorScheme.DARK})`).matches;
if (noPreference) {
return ColorScheme.NO_PREFERENCE;
} else if (prefersDark) {
return ColorScheme.DARK;
private getPreferredColorScheme(): ThemeType | undefined {
let detectHCThemeSetting = this.configurationService.getValue<boolean>(DETECT_HC_SETTING);
if (this.environmentService.configuration.highContrast && detectHCThemeSetting) {
return HIGH_CONTRAST;
}
return ColorScheme.LIGHT;
if (this.configurationService.getValue<boolean>(DETECT_COLOR_SCHEME_SETTING)) {
if (window.matchMedia(`(prefers-color-scheme: light)`).matches) {
return LIGHT;
} else if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) {
return DARK;
}
}
return undefined;
}
private getPreferredColorTheme(type: ThemeType): Promise<ColorThemeData | undefined> {
const settingId = type === DARK ? PREFERRED_DARK_THEME_SETTING : type === LIGHT ? PREFERRED_LIGHT_THEME_SETTING : PREFERRED_HC_THEME_SETTING;
const themeSettingId = this.configurationService.getValue<string>(settingId);
if (themeSettingId) {
return this.colorThemeStore.findThemeDataBySettingsId(themeSettingId, undefined);
}
return Promise.resolve(undefined);
}
public getColorTheme(): IColorTheme {
......@@ -735,22 +707,25 @@ const colorThemeSettingSchema: IConfigurationPropertySchema = {
enumDescriptions: [],
errorMessage: nls.localize('colorThemeError', "Theme is unknown or not installed."),
};
const colorThemeDarkSettingSchema: IConfigurationPropertySchema = {
const preferredDarkThemeSettingSchema: IConfigurationPropertySchema = {
type: 'string',
description: nls.localize('colorThemeDark', 'Specifies the color theme used for a dark OS appearance.'),
description: nls.localize('preferredDarkColorTheme', 'Specifies the preferred color theme for dark OS appearance when \'{0}\' is enabled.', DETECT_COLOR_SCHEME_SETTING),
default: DEFAULT_THEME_DARK_SETTING_VALUE,
errorMessage: nls.localize('colorThemeError', "Theme is unknown or not installed."),
};
const colorThemeLightSettingSchema: IConfigurationPropertySchema = {
const preferredLightThemeSettingSchema: IConfigurationPropertySchema = {
type: 'string',
description: nls.localize('colorThemeLight', 'Specifies the color theme used for a light OS appearance.'),
description: nls.localize('preferredLightColorTheme', 'Specifies the preferred color theme for light OS appearance when \'{0}\' is enabled.', DETECT_COLOR_SCHEME_SETTING),
default: DEFAULT_THEME_LIGHT_SETTING_VALUE,
errorMessage: nls.localize('colorThemeError', "Theme is unknown or not installed."),
};
const colorThemeAutoSwitchSettingSchema: IConfigurationPropertySchema = {
const preferredHCThemeSettingSchema: IConfigurationPropertySchema = {
type: 'string',
description: nls.localize('preferredHCColorTheme', 'Specifies the preferred color theme used in high contrast mode when \'{0}\' is enabled.', DETECT_HC_SETTING),
default: DEFAULT_THEME_HC_SETTING_VALUE,
};
const detectColorSchemeSettingSchema: IConfigurationPropertySchema = {
type: 'boolean',
description: nls.localize('colorThemeAutoSwitch', 'Changes the color theme based on the OS appearance.'),
default: DEFAULT_THEME_AUTO_SWITCH_SETTING_VALUE
description: nls.localize('detectColorScheme', 'If set, use the prefered color theme based on the OS appearance.'),
default: true
};
const iconThemeSettingSchema: IConfigurationPropertySchema = {
......@@ -778,9 +753,10 @@ const themeSettingsConfiguration: IConfigurationNode = {
type: 'object',
properties: {
[COLOR_THEME_SETTING]: colorThemeSettingSchema,
[COLOR_THEME_DARK_SETTING]: colorThemeDarkSettingSchema,
[COLOR_THEME_LIGHT_SETTING]: colorThemeLightSettingSchema,
[DETECT_AS_SETTING]: colorThemeAutoSwitchSettingSchema,
[PREFERRED_DARK_THEME_SETTING]: preferredDarkThemeSettingSchema,
[PREFERRED_LIGHT_THEME_SETTING]: preferredLightThemeSettingSchema,
[PREFERRED_HC_THEME_SETTING]: preferredHCThemeSettingSchema,
[DETECT_COLOR_SCHEME_SETTING]: detectColorSchemeSettingSchema,
[ICON_THEME_SETTING]: iconThemeSettingSchema,
[CUSTOM_WORKBENCH_COLORS_SETTING]: colorCustomizationsSchema
}
......@@ -839,4 +815,4 @@ const tokenColorCustomizationConfiguration: IConfigurationNode = {
};
configurationRegistry.registerConfiguration(tokenColorCustomizationConfiguration);
registerSingleton(IWorkbenchThemeService, WorkbenchThemeService);
\ No newline at end of file
registerSingleton(IWorkbenchThemeService, WorkbenchThemeService);
......@@ -18,10 +18,6 @@ export const VS_HC_THEME = 'hc-black';
export const HC_THEME_ID = 'Default High Contrast';
export const COLOR_THEME_SETTING = 'workbench.colorTheme';
export const COLOR_THEME_DARK_SETTING = 'workbench.colorThemeDark';
export const COLOR_THEME_LIGHT_SETTING = 'workbench.colorThemeLight';
export const DETECT_AS_SETTING = 'workbench.colorThemeAutoSwitch';
export const DETECT_HC_SETTING = 'window.autoDetectHighContrast';
export const ICON_THEME_SETTING = 'workbench.iconTheme';
export const CUSTOM_WORKBENCH_COLORS_SETTING = 'workbench.colorCustomizations';
export const CUSTOM_EDITOR_COLORS_SETTING = 'editor.tokenColorCustomizations';
......@@ -114,4 +110,4 @@ export interface IThemeExtensionPoint {
path: string;
uiTheme?: typeof VS_LIGHT_THEME | typeof VS_DARK_THEME | typeof VS_HC_THEME;
_watch: boolean; // unsupported options to watch location
}
\ No newline at end of file
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册