Files
ashell/src/app/theme.rs
T
TomZz bd376935f4 feat: add keybinding management
解决了 #18。

验证:

- cargo fmt

- cargo check

- git diff --check
2026-06-15 20:32:05 +08:00

163 lines
5.4 KiB
Rust

use anyhow::{Context as _, Result};
use gpui::{App, Context, SharedString, Window, px};
use gpui_component::{ActiveTheme as _, Theme, ThemeMode, ThemeRegistry};
use crate::Ashell;
pub(crate) const EMBEDDED_THEME_JSONS: &[&str] = &[
include_str!("../../assets/themes/matrix.json"),
include_str!("../../assets/themes/tokyonight.json"),
include_str!("../../assets/themes/gruvbox.json"),
include_str!("../../assets/themes/solarized.json"),
];
pub(crate) fn load_fonts(cx: &mut App) -> Result<()> {
let regular = std::borrow::Cow::Borrowed(
include_bytes!("../../assets/fonts/MapleMono-NF-CN-Regular.ttf").as_slice(),
);
let bold = std::borrow::Cow::Borrowed(
include_bytes!("../../assets/fonts/MapleMono-NF-CN-Bold.ttf").as_slice(),
);
cx.text_system()
.add_fonts(vec![regular, bold])
.context("load Maple Mono NF CN fonts")?;
set_theme_font_names(cx.global_mut::<Theme>(), ".SystemUIFont");
Ok(())
}
pub(crate) fn load_embedded_themes(cx: &mut App) {
let registry = ThemeRegistry::global_mut(cx);
for theme_json in EMBEDDED_THEME_JSONS {
if let Err(err) = registry.load_themes_from_str(theme_json) {
tracing::warn!("failed to load embedded theme: {err:#}");
}
}
}
pub(crate) fn set_theme_font_names(theme: &mut Theme, ui_font_family: &str) {
theme.font_family = ui_font_family.into();
theme.mono_font_family = ui_font_family.into();
}
impl Ashell {
pub(crate) fn switch_theme_mode(
&mut self,
mode: ThemeMode,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.follow_system_theme = false;
self.theme_mode = mode;
self.apply_theme_preferences(window, cx);
self.status = format!("theme mode: {}", cx.theme().mode.name()).into();
self.persist_theme_preferences();
cx.notify();
}
pub(crate) fn apply_theme(
&mut self,
name: SharedString,
window: &mut Window,
cx: &mut Context<Self>,
) {
let Some(theme_config) = ThemeRegistry::global(cx).themes().get(&name).cloned() else {
self.status = format!("theme not found: {name}").into();
cx.notify();
return;
};
if theme_config.mode.is_dark() {
self.dark_theme_name = name.clone();
} else {
self.light_theme_name = name.clone();
}
self.apply_theme_preferences(window, cx);
self.status = format!("theme: {name}").into();
self.persist_theme_preferences();
window.refresh();
cx.notify();
}
pub(crate) fn set_follow_system_theme(
&mut self,
follow: bool,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.follow_system_theme = follow;
if follow {
self.status = "theme mode: system".into();
} else {
self.status = format!("theme mode: {}", cx.theme().mode.name()).into();
}
self.apply_theme_preferences(window, cx);
self.persist_theme_preferences();
cx.notify();
}
pub(crate) fn set_display_language(
&mut self,
locale: &str,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.config.set_locale(locale);
let mut active_locale = locale.to_string();
if active_locale == "system" {
active_locale = sys_locale::get_locale().unwrap_or_else(|| "en".to_string());
if active_locale.starts_with("zh") {
active_locale = "zh-CN".to_string();
} else {
active_locale = "en".to_string();
}
}
rust_i18n::set_locale(&active_locale);
gpui_component::set_locale(&active_locale);
if let Err(err) = self.config.save() {
tracing::warn!("failed to save language preferences: {err:#}");
}
window.refresh();
cx.notify();
}
pub(crate) fn apply_theme_preferences(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let light_theme = ThemeRegistry::global(cx)
.themes()
.get(&self.light_theme_name)
.cloned()
.unwrap_or_else(|| ThemeRegistry::global(cx).default_light_theme().clone());
let dark_theme = ThemeRegistry::global(cx)
.themes()
.get(&self.dark_theme_name)
.cloned()
.unwrap_or_else(|| ThemeRegistry::global(cx).default_dark_theme().clone());
let theme = Theme::global_mut(cx);
theme.light_theme = light_theme;
theme.dark_theme = dark_theme;
theme.font_size = px(self.ui_font_size);
set_theme_font_names(theme, &self.ui_font_family);
if self.follow_system_theme {
Theme::sync_system_appearance(Some(window), cx);
} else {
Theme::change(self.theme_mode, Some(window), cx);
}
}
pub(crate) fn persist_theme_preferences(&mut self) {
let theme_mode_str = match self.theme_mode {
ThemeMode::Light => "light",
ThemeMode::Dark => "dark",
};
self.config.set_theme_preferences(
self.follow_system_theme,
theme_mode_str,
self.light_theme_name.to_string(),
self.dark_theme_name.to_string(),
);
if let Err(err) = self.config.save() {
tracing::warn!("failed to save theme preferences: {err:#}");
}
}
}