Reload themes defined in extensions (#7520)

This PR extends the extension directory watcher to also watch and reload
themes defined in extensions.

Release Notes:

- N/A

Co-authored-by: Max <max@zed.dev>
This commit is contained in:
Marshall Bowers 2024-02-07 16:11:24 -05:00 committed by GitHub
parent 31d9edfaaa
commit 2f4bb79553
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 71 additions and 16 deletions

View File

@ -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<LanguageRegistry>,
theme_registry: Arc<ThemeRegistry>,
_watch_extensions_dir: Task<()>,
_watch_extensions_dir: [Task<()>; 2],
}
struct GlobalExtensionStore(Model<ExtensionStore>);
@ -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<Self>) -> Task<()> {
fn watch_extensions_dir(&self, cx: &mut ModelContext<Self>) -> [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<Self>) -> Task<Result<()>> {

View File

@ -33,6 +33,20 @@ pub struct ThemeSettings {
pub theme_overrides: Option<ThemeStyleContent>,
}
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);