From 0b9f8e783272be42197bca1769ec49bc9ae9e190 Mon Sep 17 00:00:00 2001 From: jiming Date: Tue, 25 Jan 2022 17:38:54 +0800 Subject: [PATCH] feat: support to get the mode of the current Color Theme --- src/common/__tests__/utils.test.ts | 7 +++- src/common/utils.ts | 41 +++++++++++++++++++ src/model/colorTheme.ts | 5 +++ .../__tests__/colorThemeService.test.ts | 33 +++++++++++++++ src/services/theme/colorThemeService.ts | 31 +++++++++++++- 5 files changed, 114 insertions(+), 3 deletions(-) diff --git a/src/common/__tests__/utils.test.ts b/src/common/__tests__/utils.test.ts index 6052b23f3..57397c950 100644 --- a/src/common/__tests__/utils.test.ts +++ b/src/common/__tests__/utils.test.ts @@ -1,4 +1,4 @@ -import { normalizeFlattedObject } from '../utils'; +import { normalizeFlattedObject, colorLightOrDark } from '../utils'; describe('Test Utils', () => { test('The normalizeFlattedObject function', () => { @@ -35,4 +35,9 @@ describe('Test Utils', () => { const normalized = normalizeFlattedObject(testData); expect(normalized).toEqual(expected); }); + + test('The colorLightOrDark function', () => { + expect(colorLightOrDark('#000')).toBe('dark'); + expect(colorLightOrDark('rgb(255,255,255)')).toBe('light'); + }); }); diff --git a/src/common/utils.ts b/src/common/utils.ts index 9735198ea..6db301c02 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -106,3 +106,44 @@ export function normalizeFlattedObject(target: object): object { } return normalized; } + +/** + * Determine if a color is light or dark. + * @param color HEX or RGB + */ +export function colorLightOrDark(color: string) { + // Variables for red, green, blue values + let r: number; + let g: number; + let b: number; + + // Check the format of the color, HEX or RGB? + if (color.match(/^rgb/)) { + // If RGB --> store the red, green, blue values in separate variables + const matchArray = + color.match( + /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/ + ) || []; + r = +matchArray[1]; + g = +matchArray[2]; + b = +matchArray[3]; + } else { + // If hex --> Convert it to RGB + let rgbNum = +('0x' + color.slice(1, 7)); + if (color.length < 5) { + rgbNum = +('0x' + color.slice(1).replace(/./g, '$&$&').slice(0, 6)); + } + r = rgbNum >> 16; + g = (rgbNum >> 8) & 255; + b = rgbNum & 255; + } + + // HSP (Highly Sensitive Poo) equation from http://alienryderflex.com/hsp.html + const hsp = Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b)); + + // Using the HSP value, determine whether the color is light or dark + if (hsp > 127.5) { + return 'light'; + } + return 'dark'; +} diff --git a/src/model/colorTheme.ts b/src/model/colorTheme.ts index c05f78c8d..08aaa3fac 100644 --- a/src/model/colorTheme.ts +++ b/src/model/colorTheme.ts @@ -16,6 +16,11 @@ export enum ColorScheme { HIGH_CONTRAST = 'hc', } +export enum ColorThemeMode { + dark = 'dark', + light = 'light', +} + export interface IColorTheme { /** * The id of component, theme will be applied by this ID diff --git a/src/services/__tests__/colorThemeService.test.ts b/src/services/__tests__/colorThemeService.test.ts index c6d63d7ec..e2f7e7631 100644 --- a/src/services/__tests__/colorThemeService.test.ts +++ b/src/services/__tests__/colorThemeService.test.ts @@ -7,6 +7,7 @@ import { ColorThemeService, DEFAULT_THEME_CLASS_NAME, } from '../theme/colorThemeService'; +import { ColorThemeMode, ColorScheme } from 'mo/model/colorTheme'; const DarkTestTheme = { id: 'Default Test', @@ -133,4 +134,36 @@ describe('The Color Theme Service', () => { colorThemeService.updateTheme(DarkTestTheme); }); }); + + test('Should support to get colorThemeMode', () => { + colorThemeService.updateTheme({ + ...BuiltInColorTheme, + type: ColorScheme.DARK, + }); + expect(colorThemeService.getColorThemeMode()).toBe(ColorThemeMode.dark); + + colorThemeService.updateTheme({ + ...BuiltInColorTheme, + type: ColorScheme.LIGHT, + }); + expect(colorThemeService.getColorThemeMode()).toBe( + ColorThemeMode.light + ); + + colorThemeService.updateTheme({ + ...BuiltInColorTheme, + type: undefined, + colors: { + 'molecule.welcomeBackground': '#252526', + }, + }); + expect(colorThemeService.getColorThemeMode()).toBe(ColorThemeMode.dark); + + colorThemeService.updateTheme({ + ...BuiltInColorTheme, + type: undefined, + colors: {}, + }); + expect(colorThemeService.getColorThemeMode()).toBe(ColorThemeMode.dark); + }); }); diff --git a/src/services/theme/colorThemeService.ts b/src/services/theme/colorThemeService.ts index 95225b28e..f3db103b4 100644 --- a/src/services/theme/colorThemeService.ts +++ b/src/services/theme/colorThemeService.ts @@ -4,14 +4,14 @@ */ import 'reflect-metadata'; -import { IColorTheme } from 'mo/model/colorTheme'; +import { IColorTheme, ColorThemeMode, ColorScheme } from 'mo/model/colorTheme'; import { singleton } from 'tsyringe'; import { editor as monacoEditor } from 'mo/monaco'; import { applyStyleSheetRules } from 'mo/common/css'; import { getThemeData, convertToCSSVars } from './helper'; import logger from 'mo/common/logger'; import { prefixClaName } from 'mo/common/className'; -import { searchById } from 'mo/common/utils'; +import { searchById, colorLightOrDark } from 'mo/common/utils'; export interface IColorThemeService { /** @@ -53,6 +53,10 @@ export interface IColorThemeService { * Reset theme */ reset(): void; + /** + * Get the mode('dark' or 'light') of the current Color Theme + */ + getColorThemeMode(): ColorThemeMode; } /** @@ -153,4 +157,27 @@ export class ColorThemeService implements IColorThemeService { this.colorThemes = [BuiltInColorTheme]; this.setTheme(BuiltInColorTheme.id); } + + public getColorThemeMode(): ColorThemeMode { + const { colors, type } = this.colorTheme; + + // Try to get colorThemeMode from type + if (type === ColorScheme.DARK || type === ColorScheme.HIGH_CONTRAST) { + return ColorThemeMode.dark; + } else if (type === ColorScheme.LIGHT) { + return ColorThemeMode.light; + } + + // Try to get colorThemeMode from background color + const background = + colors?.['editor.background'] || + colors?.['tab.activeBackground'] || + colors?.['molecule.welcomeBackground']; + if (background) { + return colorLightOrDark(background) as ColorThemeMode; + } + + // Default dark + return ColorThemeMode.dark; + } }