New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement auto switch of color theme based on browser API prefers-color-scheme
(WIP)
#86600
Conversation
This implements three new options to the workspace scope. One to enable/ disable the auto switch functionality and two others to set the dark and light theme.
Oh, very sorry for that much line changes... Seems like prettier does something different in my VS Code instance than in the one from the authors I guess. Would love to get some help to fix this, so it won't happen again or more strict rules in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
@@ -72,6 +75,8 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { | |||
|
|||
private colorThemeStore: ColorThemeStore; | |||
private currentColorTheme: ColorThemeData; | |||
private autoSwitchColorTheme = DEFAULT_THEME_AUTO_SWITCH_SETTING_VALUE; | |||
private autoSwitchColorThemeListener: MediaQueryList | undefined = undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to follow the typical way we do this: Make this of type IDisposable | undefined.
dispose would uninstall the listener.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, autoSwitchColorTheme and autoSwitchColorThemeListener can be folded into one.
if autoSwitchColorThemeListener is defined-> autoswitch is on. if undefined: off
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think IDisposable
does not work here because matchMedia
returns a MediaQueryList
. I will merge it into one but will leave the MediaQueryList | undefined
@@ -114,6 +119,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { | |||
this.iconThemeStore = new FileIconThemeStore(extensionService); | |||
this.onColorThemeChange = new Emitter<IColorTheme>({ leakWarningThreshold: 400 }); | |||
|
|||
this.onPreferColorSchemeChange = this.onPreferColorSchemeChange.bind(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needed, otherwise the function could not access WorkbenchThemeService
but if you know another implementation let me know.
@@ -18,12 +18,22 @@ 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'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given we already have'window.autoDetectHighContrast'
, what about calling it:
'window.autoDetectColorScheme': true | false
and
'workbench.preferredLightColorTheme'
'workbench.preferredDarkColorTheme'
'workbench.preferredHighConstrastColorTheme'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thought was that even if HC is on, there can also be light and dark HC themes and give it the prefix colorTheme
would make it easier to find in settings or more present to the user. Not everyone will know that this feature exists but sure preferred
as prefix would make more sense and match to the browser API with prefers-color-scheme
.
Would like to hear what a third or fourth person is saying about this here.
src/vs/workbench/services/themes/common/workbenchThemeService.ts
Outdated
Show resolved
Hide resolved
src/vs/workbench/services/themes/browser/workbenchThemeService.ts
Outdated
Show resolved
Hide resolved
src/vs/workbench/services/themes/browser/workbenchThemeService.ts
Outdated
Show resolved
Hide resolved
src/vs/workbench/services/themes/common/workbenchThemeService.ts
Outdated
Show resolved
Hide resolved
src/vs/workbench/services/themes/common/workbenchThemeService.ts
Outdated
Show resolved
Hide resolved
|
||
let colorThemeSetting: string; | ||
let detectThemeAutoSwitch = this.configurationService.getValue<boolean>(DETECT_AS_SETTING); | ||
this.autoSwitchColorTheme = detectThemeAutoSwitch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should only switch the theme if the current theme is not of the same mode (dark/light/hc).
Do lets say I have 'Dark+' as my preferredDarkTheme, but at some point switched to use Monokai. When I enable autoSwitch. it is detected that dark is the window theme mode. But Monokai is dark, all is fine, no need to switch.
Same when VSCode is restarted.
So the 'prefferred' themes are only really used when there's a switch from the OS. The switch can be while we are open and we get the event, or while VSCode was closed, so we only see the mismatch when starting up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do lets say I have 'Dark+' as my preferredDarkTheme, but at some point switched to use Monokai. When I enable autoSwitch. it is detected that dark is the window theme mode. But Monokai is dark, all is fine, no need to switch.
You mean like this (in: e.affectsConfiguration(COLOR_THEME_SETTING)
)?
// if "auto switch" and (OS dark == theme dark) => update preferred dark theme
// if "auto switch" and (OS light == theme light) => update preferred light theme
// set new theme
So the 'prefferred' themes are only really used when there's a switch from the OS. The switch can be while we are open and we get the event, or while VSCode was closed, so we only see the mismatch when starting up.
Isn't this the current case?
I have updated it, please check if this is solved.
This PR implements the functionality to auto switch the Code color theme based on the users preferred OS appearance setting. It makes use of the browser
matchMedia
API, which makes it compatible with the VS Code Browser version as well.What has changed?
The
colorTheme
prop is as before the place where the current theme is set, but now there are three new props:colorThemeAutoSwitch
: this enables/disables the auto switch functionalitycolorThemeDark
: holds the theme for "dark mode"colorThemeLight
: holds the theme for "light mode"VS Code will now listen on the match media event to respond to OS appearance changes. I have tested it in the browser and it works good and very smooth.
To make the code more readable and to not repeat myself, I have created some extra functions inside
WorkbenchThemeService
, I hope this is okay. The changes also include listening on VS Code settings changes to disable the feature if someone changes the theme manually to prevent loops or flickering. Also, I don't think someone wants this feature if he's doing it manually.It is enabled by default, I think this is good, to force developers to take more care about their eyes in dark environments.
How to test?
yarn install
yarn watch-client
yarn web
Next?
Here are the things that are still needed to finish up before a merge can be done. I also would need some help on some points. Would appreciate anyone that can comment to some of them.
console.logs
(haven't removed them for debugging ATM)colorThemeDark
andcolorThemeLight
selectable dropdown of theme options (Status: NEEDS HELP)onThemeSwitch/Change
which would return the new theme or 'dark', 'light' or 'no-preference' based on the browser APIgetPreferredScheme
which would return 'dark', 'light' or 'no-preference' based on the browser APIThis PR fixes #61519