add accent color and surface preferences to settings
This commit is contained in:
@@ -318,6 +318,34 @@ impl AppSettings {
|
||||
self.apply_theme(Some(window), cx);
|
||||
}
|
||||
|
||||
/// Set the accent color override and re-resolve the theme
|
||||
pub fn apply_accent(
|
||||
&mut self,
|
||||
selection: AccentSelection,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.inner.update(cx, |this, cx| {
|
||||
this.accent_selection = selection;
|
||||
cx.notify();
|
||||
});
|
||||
self.apply_theme(Some(window), cx);
|
||||
}
|
||||
|
||||
/// Set the surface treatment preference
|
||||
pub fn apply_surface(
|
||||
&mut self,
|
||||
preference: SurfacePreference,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.inner.update(cx, |this, cx| {
|
||||
this.surface_preference = preference;
|
||||
cx.notify();
|
||||
});
|
||||
self.apply_theme(Some(window), cx);
|
||||
}
|
||||
|
||||
/// Apply theme
|
||||
pub fn apply_theme(&mut self, window: Option<&mut Window>, cx: &mut Context<Self>) {
|
||||
let (selection, accent, surface, appearance) = {
|
||||
|
||||
@@ -36,6 +36,10 @@ pub const TABBAR_HEIGHT: Pixels = px(36.0);
|
||||
pub const SIDEBAR_WIDTH: Pixels = px(240.);
|
||||
|
||||
pub fn init(cx: &mut App) {
|
||||
for issue in ThemeRegistry::active().validate() {
|
||||
log::warn!("theme {}: {}", issue.variant_id, issue.message);
|
||||
}
|
||||
|
||||
Theme::sync_system_appearance(None, cx);
|
||||
Theme::sync_scrollbar_appearance(cx);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use gpui::{
|
||||
Window, div, px,
|
||||
};
|
||||
use settings::AppSettings;
|
||||
use theme::{ActiveTheme, Appearance, Theme};
|
||||
use theme::{AccentPreset, AccentSelection, ActiveTheme, Appearance, SurfacePreference, Theme};
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::group_box::{GroupBox, GroupBoxVariants};
|
||||
use ui::input::{Input, InputState};
|
||||
@@ -59,6 +59,8 @@ impl Render for Preferences {
|
||||
const SCREENING: &str = "Show an screening dialog to verify the unknown sender.";
|
||||
const AVATAR: &str = "Hide all avatar pictures to improve performance.";
|
||||
const MODE: &str = "Use the selected light or dark theme, or to follow the OS.";
|
||||
const ACCENT: &str = "Override the accent color of the selected theme.";
|
||||
const SURFACE: &str = "Preferred surface treatment. Frosted rendering is not applied yet.";
|
||||
const NIP4E: &str = "Use a dedicated key to encrypt and decrypt messages.";
|
||||
const RESET: &str = "Reset the theme to the default one.";
|
||||
|
||||
@@ -66,6 +68,8 @@ impl Render for Preferences {
|
||||
let hide_avatar = AppSettings::get_hide_avatar(cx);
|
||||
let nip4e = AppSettings::get_nip4e(cx);
|
||||
let appearance = AppSettings::get_appearance(cx);
|
||||
let accent_selection = AppSettings::get_accent_selection(cx);
|
||||
let surface_preference = AppSettings::get_surface_preference(cx);
|
||||
|
||||
v_flex()
|
||||
.gap_4()
|
||||
@@ -135,6 +139,127 @@ impl Render for Preferences {
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_3()
|
||||
.justify_between()
|
||||
.child(
|
||||
v_flex()
|
||||
.child(div().text_sm().child(SharedString::from("Accent")))
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child(SharedString::from(ACCENT)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new("accent")
|
||||
.label(accent_selection.label())
|
||||
.ghost_alt()
|
||||
.small()
|
||||
.dropdown_menu(|menu, _window, _cx| {
|
||||
let menu =
|
||||
menu.item(
|
||||
PopupMenuItem::new(
|
||||
AccentSelection::ThemeDefault.label(),
|
||||
)
|
||||
.on_click(|_, window, cx| {
|
||||
AppSettings::global(cx).update(cx, |s, cx| {
|
||||
s.apply_accent(
|
||||
AccentSelection::ThemeDefault,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
let mut menu = menu;
|
||||
for preset in AccentPreset::ALL {
|
||||
menu = menu.item(
|
||||
PopupMenuItem::new(preset.label()).on_click({
|
||||
move |_, window, cx| {
|
||||
AppSettings::global(cx).update(
|
||||
cx,
|
||||
|s, cx| {
|
||||
s.apply_accent(
|
||||
AccentSelection::Preset(preset),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
menu
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_3()
|
||||
.justify_between()
|
||||
.child(
|
||||
v_flex()
|
||||
.child(div().text_sm().child(SharedString::from("Surface")))
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child(SharedString::from(SURFACE)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new("surface")
|
||||
.label(match surface_preference {
|
||||
SurfacePreference::ThemeDefault => "Theme default",
|
||||
SurfacePreference::Frosted => "Frosted",
|
||||
SurfacePreference::Opaque => "Opaque",
|
||||
})
|
||||
.ghost_alt()
|
||||
.small()
|
||||
.dropdown_menu(|menu, _window, _cx| {
|
||||
menu.item(PopupMenuItem::new("Theme default").on_click(
|
||||
|_, window, cx| {
|
||||
AppSettings::global(cx).update(cx, |s, cx| {
|
||||
s.apply_surface(
|
||||
SurfacePreference::ThemeDefault,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
},
|
||||
))
|
||||
.item(PopupMenuItem::new("Frosted").on_click(
|
||||
|_, window, cx| {
|
||||
AppSettings::global(cx).update(cx, |s, cx| {
|
||||
s.apply_surface(
|
||||
SurfacePreference::Frosted,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
},
|
||||
))
|
||||
.item(
|
||||
PopupMenuItem::new("Opaque").on_click(
|
||||
|_, window, cx| {
|
||||
AppSettings::global(cx).update(cx, |s, cx| {
|
||||
s.apply_surface(
|
||||
SurfacePreference::Opaque,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_3()
|
||||
|
||||
@@ -465,17 +465,42 @@ impl Workspace {
|
||||
|
||||
fn theme_selector(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let appearance = cx.theme().appearance;
|
||||
let variants: Vec<ThemeVariant> = ThemeRegistry::active()
|
||||
.variants_for(appearance)
|
||||
let registry = ThemeRegistry::active();
|
||||
let groups: Vec<(String, Vec<ThemeVariant>)> = registry
|
||||
.families
|
||||
.iter()
|
||||
.filter_map(|family| {
|
||||
let variants: Vec<ThemeVariant> = family
|
||||
.variants
|
||||
.iter()
|
||||
.filter(|variant| variant.appearance == appearance)
|
||||
.cloned()
|
||||
.collect();
|
||||
if variants.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some((family.name.clone(), variants))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
window.open_dialog(cx, move |this, _window, cx| {
|
||||
this.width(px(520.))
|
||||
.show_close(true)
|
||||
.title("Select theme")
|
||||
.child(v_flex().gap_2().w_full().children({
|
||||
let mut items = vec![];
|
||||
let mut items: Vec<gpui::AnyElement> = vec![];
|
||||
|
||||
for (family_name, variants) in groups.iter() {
|
||||
items.push(
|
||||
div()
|
||||
.pt_2()
|
||||
.text_xs()
|
||||
.italic()
|
||||
.text_color(cx.theme().text_faint)
|
||||
.child(SharedString::from(family_name.clone()))
|
||||
.into_any_element(),
|
||||
);
|
||||
|
||||
for (ix, variant) in variants.iter().enumerate() {
|
||||
items.push(
|
||||
@@ -499,9 +524,9 @@ impl Workspace {
|
||||
div()
|
||||
.text_xs()
|
||||
.italic()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().text_faint)
|
||||
.child(SharedString::from(
|
||||
variant.family_id.clone(),
|
||||
variant.source.license.clone(),
|
||||
)),
|
||||
),
|
||||
)
|
||||
@@ -542,9 +567,11 @@ impl Workspace {
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.into_any_element(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
items
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user