diff --git a/crates/extension/src/extension_store.rs b/crates/extension/src/extension_store.rs index 9b9892641d..fffaac44e4 100644 --- a/crates/extension/src/extension_store.rs +++ b/crates/extension/src/extension_store.rs @@ -14,7 +14,7 @@ use std::{ sync::Arc, time::Duration, }; -use theme::ThemeRegistry; +use theme::{ThemeRegistry, ThemeSettings}; use util::{paths::EXTENSIONS_DIR, ResultExt}; #[cfg(test)] @@ -27,7 +27,7 @@ pub struct ExtensionStore { manifest_path: PathBuf, language_registry: Arc, theme_registry: Arc, - _watch_extensions_dir: Task<()>, + _watch_extensions_dir: [Task<()>; 2], } struct GlobalExtensionStore(Model); @@ -103,7 +103,7 @@ impl ExtensionStore { fs, language_registry, theme_registry, - _watch_extensions_dir: Task::ready(()), + _watch_extensions_dir: [Task::ready(()), Task::ready(())], }; this._watch_extensions_dir = this.watch_extensions_dir(cx); this.load(cx); @@ -176,30 +176,71 @@ impl ExtensionStore { *self.manifest.write() = manifest; } - fn watch_extensions_dir(&self, cx: &mut ModelContext) -> Task<()> { + fn watch_extensions_dir(&self, cx: &mut ModelContext) -> [Task<()>; 2] { let manifest = self.manifest.clone(); let fs = self.fs.clone(); let language_registry = self.language_registry.clone(); + let theme_registry = self.theme_registry.clone(); let extensions_dir = self.extensions_dir.clone(); - cx.background_executor().spawn(async move { - let mut changed_languages = HashSet::default(); + + let (reload_theme_tx, mut reload_theme_rx) = futures::channel::mpsc::unbounded(); + + let events_task = cx.background_executor().spawn(async move { let mut events = fs.watch(&extensions_dir, Duration::from_millis(250)).await; while let Some(events) = events.next().await { - changed_languages.clear(); - let manifest = manifest.read(); - for event in events { - for (language_name, language) in &manifest.languages { - let mut language_path = extensions_dir.clone(); - language_path - .extend([language.extension.as_ref(), language.path.as_path()]); - if event.path.starts_with(&language_path) || event.path == language_path { - changed_languages.insert(language_name.clone()); + let mut changed_languages = HashSet::default(); + let mut changed_themes = HashSet::default(); + + { + let manifest = manifest.read(); + for event in events { + for (language_name, language) in &manifest.languages { + let mut language_path = extensions_dir.clone(); + language_path + .extend([language.extension.as_ref(), language.path.as_path()]); + if event.path.starts_with(&language_path) || event.path == language_path + { + changed_languages.insert(language_name.clone()); + } + } + + for (_theme_name, theme) in &manifest.themes { + let mut theme_path = extensions_dir.clone(); + theme_path.extend([theme.extension.as_ref(), theme.path.as_path()]); + if event.path.starts_with(&theme_path) || event.path == theme_path { + changed_themes.insert(theme_path.clone()); + } } } } + language_registry.reload_languages(&changed_languages); + + for theme_path in &changed_themes { + theme_registry + .load_user_theme(&theme_path, fs.clone()) + .await + .log_err(); + } + + if !changed_themes.is_empty() { + reload_theme_tx.unbounded_send(()).ok(); + } } - }) + }); + + let reload_theme_task = cx.spawn(|_, cx| async move { + while let Some(_) = reload_theme_rx.next().await { + if cx + .update(|cx| ThemeSettings::reload_current_theme(cx)) + .is_err() + { + break; + } + } + }); + + [events_task, reload_theme_task] } pub fn reload(&mut self, cx: &mut ModelContext) -> Task> { diff --git a/crates/theme/src/settings.rs b/crates/theme/src/settings.rs index dd16239708..535646fb25 100644 --- a/crates/theme/src/settings.rs +++ b/crates/theme/src/settings.rs @@ -33,6 +33,20 @@ pub struct ThemeSettings { pub theme_overrides: Option, } +impl ThemeSettings { + pub fn reload_current_theme(cx: &mut AppContext) { + let mut theme_settings = ThemeSettings::get_global(cx).clone(); + + if let Some(theme_selection) = theme_settings.theme_selection.clone() { + let theme_name = theme_selection.theme(*SystemAppearance::global(cx)); + + if let Some(_theme) = theme_settings.switch_theme(&theme_name, cx) { + ThemeSettings::override_global(theme_settings, cx); + } + } + } +} + /// The appearance of the system. #[derive(Debug, Clone, Copy, Deref)] pub struct SystemAppearance(pub Appearance);