Files
oak-gpui/crates/theme_extension/src/theme_extension.rs
T
Marshall Bowers f53915c711 Add infrastructure for loading icon themes from extensions (#23203)
This PR adds the supporting infrastructure to support loading icon
themes defined by extensions.

Here's an example icon theme:

```json
{
  "name": "My Icon Theme",
  "author": "Me <me@example.com>",
  "themes": [
    {
      "name": "My Icon Theme",
      "appearance": "dark",
      "file_icons": {
        "gleam": { "path": "./icons/file_type_gleam.svg" },
        "toml": { "path": "./icons/file_type_toml.svg" }
      }
    }
  ]
}
```

The icon paths are resolved relative to the root of the extension
directory.

Release Notes:

- N/A
2025-01-15 23:33:47 +00:00

81 lines
2.4 KiB
Rust

use std::path::PathBuf;
use std::sync::Arc;
use anyhow::Result;
use extension::{ExtensionHostProxy, ExtensionThemeProxy};
use fs::Fs;
use gpui::{AppContext, BackgroundExecutor, SharedString, Task};
use theme::{ThemeRegistry, ThemeSettings};
pub fn init(
extension_host_proxy: Arc<ExtensionHostProxy>,
theme_registry: Arc<ThemeRegistry>,
executor: BackgroundExecutor,
) {
extension_host_proxy.register_theme_proxy(ThemeRegistryProxy {
theme_registry,
executor,
});
}
struct ThemeRegistryProxy {
theme_registry: Arc<ThemeRegistry>,
executor: BackgroundExecutor,
}
impl ExtensionThemeProxy for ThemeRegistryProxy {
fn list_theme_names(&self, theme_path: PathBuf, fs: Arc<dyn Fs>) -> Task<Result<Vec<String>>> {
self.executor.spawn(async move {
let themes = theme::read_user_theme(&theme_path, fs).await?;
Ok(themes.themes.into_iter().map(|theme| theme.name).collect())
})
}
fn remove_user_themes(&self, themes: Vec<SharedString>) {
self.theme_registry.remove_user_themes(&themes);
}
fn load_user_theme(&self, theme_path: PathBuf, fs: Arc<dyn Fs>) -> Task<Result<()>> {
let theme_registry = self.theme_registry.clone();
self.executor
.spawn(async move { theme_registry.load_user_theme(&theme_path, fs).await })
}
fn reload_current_theme(&self, cx: &mut AppContext) {
ThemeSettings::reload_current_theme(cx)
}
fn list_icon_theme_names(
&self,
icon_theme_path: PathBuf,
fs: Arc<dyn Fs>,
) -> Task<Result<Vec<String>>> {
self.executor.spawn(async move {
let icon_theme_family = theme::read_icon_theme(&icon_theme_path, fs).await?;
Ok(icon_theme_family
.themes
.into_iter()
.map(|theme| theme.name)
.collect())
})
}
fn remove_icon_themes(&self, icon_themes: Vec<SharedString>) {
self.theme_registry.remove_icon_themes(&icon_themes);
}
fn load_icon_theme(
&self,
icon_theme_path: PathBuf,
icons_root_dir: PathBuf,
fs: Arc<dyn Fs>,
) -> Task<Result<()>> {
let theme_registry = self.theme_registry.clone();
self.executor.spawn(async move {
theme_registry
.load_icon_theme(&icon_theme_path, &icons_root_dir, fs)
.await
})
}
}