diff --git a/crates/onboarding/src/editing_page.rs b/crates/onboarding/src/editing_page.rs index 47dfd84894bf0ca5e7fd4a5a9ad0785d80b07ac5..297016abd4a1499feb6f637d028056ca0b412d31 100644 --- a/crates/onboarding/src/editing_page.rs +++ b/crates/onboarding/src/editing_page.rs @@ -449,28 +449,28 @@ impl FontPickerDelegate { ) -> Self { let font_family_cache = FontFamilyCache::global(cx); - let fonts: Vec = font_family_cache - .list_font_families(cx) - .into_iter() - .collect(); - + let fonts = font_family_cache + .try_list_font_families() + .unwrap_or_else(|| vec![current_font.clone()]); let selected_index = fonts .iter() .position(|font| *font == current_font) .unwrap_or(0); + let filtered_fonts = fonts + .iter() + .enumerate() + .map(|(index, font)| StringMatch { + candidate_id: index, + string: font.to_string(), + positions: Vec::new(), + score: 0.0, + }) + .collect(); + Self { - fonts: fonts.clone(), - filtered_fonts: fonts - .iter() - .enumerate() - .map(|(index, font)| StringMatch { - candidate_id: index, - string: font.to_string(), - positions: Vec::new(), - score: 0.0, - }) - .collect(), + fonts, + filtered_fonts, selected_index, current_font, on_font_changed: Arc::new(on_font_changed), diff --git a/crates/onboarding/src/onboarding.rs b/crates/onboarding/src/onboarding.rs index 7f1bb81d4d7486ea85e23dedcb763e238d53b2f3..9dcf27c7cbebf6621bbeb558619944c768e63fb6 100644 --- a/crates/onboarding/src/onboarding.rs +++ b/crates/onboarding/src/onboarding.rs @@ -242,12 +242,25 @@ struct Onboarding { impl Onboarding { fn new(workspace: &Workspace, cx: &mut App) -> Entity { - cx.new(|cx| Self { - workspace: workspace.weak_handle(), - focus_handle: cx.focus_handle(), - selected_page: SelectedPage::Basics, - user_store: workspace.user_store().clone(), - _settings_subscription: cx.observe_global::(move |_, cx| cx.notify()), + let font_family_cache = theme::FontFamilyCache::global(cx); + + cx.new(|cx| { + cx.spawn(async move |this, cx| { + font_family_cache.prefetch(cx).await; + this.update(cx, |_, cx| { + cx.notify(); + }) + }) + .detach(); + + Self { + workspace: workspace.weak_handle(), + focus_handle: cx.focus_handle(), + selected_page: SelectedPage::Basics, + user_store: workspace.user_store().clone(), + _settings_subscription: cx + .observe_global::(move |_, cx| cx.notify()), + } }) } diff --git a/crates/settings/src/settings_ui_core.rs b/crates/settings/src/settings_ui_core.rs index 896a8bc038bdd8e495cdb6161212f9c722d54f14..e056dfbd5af486e19e2b3e8cfc038dd85c0a2549 100644 --- a/crates/settings/src/settings_ui_core.rs +++ b/crates/settings/src/settings_ui_core.rs @@ -78,6 +78,7 @@ impl SettingsValue { let fs = ::global(cx); let rx = settings_store.update_settings_file_at_path(fs.clone(), path.as_slice(), value); + let path = path.clone(); cx.background_spawn(async move { rx.await? diff --git a/crates/theme/src/font_family_cache.rs b/crates/theme/src/font_family_cache.rs index fecaf5b360a91beca3fceb564c87973d6f676384..411cf9b4d41359f4da4520061ac46c984bdd08f2 100644 --- a/crates/theme/src/font_family_cache.rs +++ b/crates/theme/src/font_family_cache.rs @@ -16,7 +16,7 @@ struct FontFamilyCacheState { /// so we do it once and then use the cached values each render. #[derive(Default)] pub struct FontFamilyCache { - state: RwLock, + state: Arc>, } #[derive(Default)] @@ -52,4 +52,44 @@ impl FontFamilyCache { lock.font_families.clone() } + + /// Returns the list of font families if they have been loaded + pub fn try_list_font_families(&self) -> Option> { + self.state + .try_read() + .filter(|state| state.loaded_at.is_some()) + .map(|state| state.font_families.clone()) + } + + /// Prefetch all font names in the background + pub async fn prefetch(&self, cx: &gpui::AsyncApp) { + if self + .state + .try_read() + .is_none_or(|state| state.loaded_at.is_some()) + { + return; + } + + let Ok(text_system) = cx.update(|cx| App::text_system(cx).clone()) else { + return; + }; + + let state = self.state.clone(); + + cx.background_executor() + .spawn(async move { + // We take this lock in the background executor to ensure that synchronous calls to `list_font_families` are blocked while we are prefetching, + // while not blocking the main thread and risking deadlocks + let mut lock = state.write(); + let all_font_names = text_system + .all_font_names() + .into_iter() + .map(SharedString::from) + .collect(); + lock.font_families = all_font_names; + lock.loaded_at = Some(Instant::now()); + }) + .await; + } }