Add support for specifying both light and dark themes in settings.json (#7404)

This PR adds support for configuring both a light and dark theme in
`settings.json`.

In addition to accepting just a theme name, the `theme` field now also
accepts an object in the following form:

```jsonc
{
  "theme": {
    "mode": "system",
    "light": "One Light",
    "dark": "One Dark"
  }
}
```

Both `light` and `dark` are required, and indicate which theme should be
used when the system is in light mode and dark mode, respectively.

The `mode` field is optional and indicates which theme should be used:
- `"system"` - Use the theme that corresponds to the system's
appearance.
- `"light"` - Use the theme indicated by the `light` field.
- `"dark"` - Use the theme indicated by the `dark` field.

Thank you to @Yesterday17 for taking a first stab at this in #6881!

Release Notes:

- Added support for configuring both a light and dark theme and
switching between them based on system preference.
This commit is contained in:
Marshall Bowers 2024-02-05 15:39:01 -05:00 committed by GitHub
parent b59f925933
commit a80a3b8706
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 167 additions and 24 deletions

View file

@ -9,7 +9,9 @@ use gpui::{
use picker::{Picker, PickerDelegate};
use settings::{update_settings_file, SettingsStore};
use std::sync::Arc;
use theme::{Theme, ThemeMeta, ThemeRegistry, ThemeSettings};
use theme::{
Appearance, Theme, ThemeMeta, ThemeMode, ThemeRegistry, ThemeSelection, ThemeSettings,
};
use ui::{prelude::*, v_flex, ListItem, ListItemSpacing};
use util::ResultExt;
use workspace::{ui::HighlightedLabel, ModalView, Workspace};
@ -167,8 +169,26 @@ impl PickerDelegate for ThemeSelectorDelegate {
self.telemetry
.report_setting_event("theme", theme_name.to_string());
let appearance = Appearance::from(cx.appearance());
update_settings_file::<ThemeSettings>(self.fs.clone(), cx, move |settings| {
settings.theme = Some(theme_name.to_string());
if let Some(selection) = settings.theme.as_mut() {
let theme_to_update = match selection {
ThemeSelection::Static(theme) => theme,
ThemeSelection::Dynamic { mode, light, dark } => match mode {
ThemeMode::Light => light,
ThemeMode::Dark => dark,
ThemeMode::System => match appearance {
Appearance::Light => light,
Appearance::Dark => dark,
},
},
};
*theme_to_update = theme_name.to_string();
} else {
settings.theme = Some(ThemeSelection::Static(theme_name.to_string()));
}
});
self.view