diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 2dc5e1510c..637200e306 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -13,7 +13,7 @@ use crate::{ ClipboardItem, Context, DispatchPhase, DisplayId, Executor, FocusEvent, FocusHandle, FocusId, KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly, Pixels, Platform, Point, SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, - TextSystem, View, Window, WindowContext, WindowHandle, WindowId, + TextSystem, View, Window, WindowContext, WindowHandle, WindowId, AnyAssetSource, }; use anyhow::{anyhow, Result}; use collections::{HashMap, HashSet, VecDeque}; @@ -66,6 +66,8 @@ impl App { os_version: platform.os_version().ok(), app_version: platform.app_version().ok(), }; + let asset_source = AnyAssetSource(asset_source); + Self(Arc::new_cyclic(|this| { Mutex::new(AppContext { this: this.clone(), @@ -76,7 +78,8 @@ impl App { pending_updates: 0, next_frame_callbacks: Default::default(), executor, - svg_renderer: SvgRenderer::new(asset_source), + svg_renderer: SvgRenderer::new(asset_source.clone()), + asset_source, image_cache: ImageCache::new(http_client), text_style_stack: Vec::new(), globals_by_type: HashMap::default(), @@ -179,6 +182,7 @@ pub struct AppContext { pub(crate) next_frame_callbacks: HashMap>, pub(crate) executor: Executor, pub(crate) svg_renderer: SvgRenderer, + asset_source: AnyAssetSource, pub(crate) image_cache: ImageCache, pub(crate) text_style_stack: Vec, pub(crate) globals_by_type: HashMap, @@ -506,6 +510,10 @@ impl AppContext { }); } + pub fn asset_source(&self) -> &AnyAssetSource { + &self.asset_source + } + pub fn text_system(&self) -> &Arc { &self.text_system } diff --git a/crates/gpui2/src/assets.rs b/crates/gpui2/src/assets.rs index cae5a8eaae..f39733d5c7 100644 --- a/crates/gpui2/src/assets.rs +++ b/crates/gpui2/src/assets.rs @@ -5,23 +5,37 @@ use std::{ borrow::Cow, fmt, hash::Hash, - sync::atomic::{AtomicUsize, Ordering::SeqCst}, + sync::{atomic::{AtomicUsize, Ordering::SeqCst}, Arc}, }; pub trait AssetSource: 'static + Send + Sync { - fn load(&self, path: &SharedString) -> Result>; - fn list(&self, path: &SharedString) -> Result>; + fn load(&self, path: SharedString) -> Result>; + fn list(&self, path: SharedString) -> Result>; } +#[derive(Clone)] +pub struct AnyAssetSource(pub(crate) Arc); + +impl AnyAssetSource { + pub fn load(&self, path: impl Into) -> Result> { + self.0.load(path.into()) + } + + pub fn list(&self, path: impl Into) -> Result> { + self.0.list(path.into()) + } +} + + impl AssetSource for () { - fn load(&self, path: &SharedString) -> Result> { + fn load(&self, path: SharedString) -> Result> { Err(anyhow!( "get called on empty asset provider with \"{}\"", path )) } - fn list(&self, _path: &SharedString) -> Result> { + fn list(&self, _path: SharedString) -> Result> { Ok(vec![]) } } diff --git a/crates/gpui2/src/svg_renderer.rs b/crates/gpui2/src/svg_renderer.rs index 068cf435b6..bfd8ca716f 100644 --- a/crates/gpui2/src/svg_renderer.rs +++ b/crates/gpui2/src/svg_renderer.rs @@ -1,7 +1,6 @@ -use crate::{AssetSource, DevicePixels, IsZero, Result, SharedString, Size}; +use crate::{DevicePixels, IsZero, Result, SharedString, Size, AnyAssetSource}; use anyhow::anyhow; use std::hash::Hash; -use std::sync::Arc; #[derive(Clone, PartialEq, Hash, Eq)] pub struct RenderSvgParams { @@ -10,11 +9,11 @@ pub struct RenderSvgParams { } pub struct SvgRenderer { - asset_source: Arc, + asset_source: AnyAssetSource, } impl SvgRenderer { - pub fn new(asset_source: Arc) -> Self { + pub fn new(asset_source: AnyAssetSource) -> Self { Self { asset_source } } @@ -24,7 +23,7 @@ impl SvgRenderer { } // Load the tree. - let bytes = self.asset_source.load(¶ms.path)?; + let bytes = self.asset_source.load(params.path.clone())?; let tree = usvg::Tree::from_data(&bytes, &usvg::Options::default())?; // Render the SVG to a pixmap with the specified width and height. diff --git a/crates/storybook2/src/assets.rs b/crates/storybook2/src/assets.rs index 76e853c0aa..c8b9fdb1fa 100644 --- a/crates/storybook2/src/assets.rs +++ b/crates/storybook2/src/assets.rs @@ -15,13 +15,13 @@ use rust_embed::RustEmbed; pub struct Assets; impl AssetSource for Assets { - fn load(&self, path: &SharedString) -> Result> { + fn load(&self, path: SharedString) -> Result> { Self::get(path.as_ref()) .map(|f| f.data) .ok_or_else(|| anyhow!("could not find asset at path \"{}\"", path)) } - fn list(&self, path: &SharedString) -> Result> { + fn list(&self, path: SharedString) -> Result> { Ok(Self::iter() .filter(|p| p.starts_with(path.as_ref())) .map(SharedString::from) diff --git a/crates/storybook2/src/storybook2.rs b/crates/storybook2/src/storybook2.rs index 2d348baac2..cc7fa6c0a0 100644 --- a/crates/storybook2/src/storybook2.rs +++ b/crates/storybook2/src/storybook2.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use clap::Parser; use gpui2::{ - div, px, size, view, AnyView, AppContext, AssetSource, Bounds, Context, Element, ViewContext, + div, px, size, view, AnyView, AppContext, Bounds, Context, Element, ViewContext, WindowBounds, WindowOptions, }; use log::LevelFilter; @@ -104,12 +104,11 @@ impl StoryWrapper { } fn load_embedded_fonts(cx: &AppContext) -> gpui2::Result<()> { - let font_paths = Assets.list(&"fonts".into())?; + let font_paths = cx.asset_source().list("fonts")?; let mut embedded_fonts = Vec::new(); - for font_path in &font_paths { + for font_path in font_paths { if font_path.ends_with(".ttf") { - let font_path = &*font_path; - let font_bytes = Assets.load(font_path)?.to_vec(); + let font_bytes = cx.asset_source().load(font_path)?.to_vec(); embedded_fonts.push(Arc::from(font_bytes)); } } diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 61e56236ea..defb90b3fd 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -67,8 +67,6 @@ fn main() { let session_id = Uuid::new_v4().to_string(); init_panic_hook(&app, installation_id.clone(), session_id.clone()); - load_embedded_fonts(&app); - let fs = Arc::new(RealFs); let user_settings_file_rx = watch_config_file(&app.executor(), fs.clone(), paths::SETTINGS.clone()); @@ -101,6 +99,7 @@ fn main() { app.run(move |cx| { cx.set_global(*RELEASE_CHANNEL); + load_embedded_fonts(cx); let mut store = SettingsStore::default(); store @@ -635,10 +634,12 @@ fn collect_url_args() -> Vec { .collect() } -fn load_embedded_fonts(app: &App) { - let font_paths = Assets.list(&"fonts".into()).unwrap(); +fn load_embedded_fonts(cx: &AppContext) { + let asset_source = cx.asset_source(); + let font_paths = asset_source.list("fonts").unwrap(); let embedded_fonts = Mutex::new(Vec::new()); - let executor = app.executor(); + let executor = cx.executor(); + executor.block(executor.scoped(|scope| { for font_path in &font_paths { if !font_path.ends_with(".ttf") { @@ -646,13 +647,13 @@ fn load_embedded_fonts(app: &App) { } scope.spawn(async { - let font_path = &*font_path; - let font_bytes = Assets.load(font_path).unwrap().to_vec(); + let font_bytes = asset_source.load(font_path).unwrap().to_vec(); embedded_fonts.lock().push(Arc::from(font_bytes)); }); } })); - app.text_system() + + cx.text_system() .add_fonts(&embedded_fonts.into_inner()) .unwrap(); }