From 9667d7882a7da1a0f5d3aa7b12c5ecec8a34250e Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Thu, 20 Nov 2025 18:28:11 -0300 Subject: [PATCH] extensions_ui: Improve error message when extensions fail to load (#43197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screenshot 2025-11-20 at 6  12@2x Release Notes: - extensions UI: Improved the feedback message for when extensions are not being displayed due to a fetch error caused by lack of connection. --- crates/extensions_ui/src/extensions_ui.rs | 51 +++++++++++++++++------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/crates/extensions_ui/src/extensions_ui.rs b/crates/extensions_ui/src/extensions_ui.rs index 657a39f09e6465042f5f1a5d113bdfa6e61c43ce..e35c90b6104b44bd6dbf3fe86aeaf84f122c04ca 100644 --- a/crates/extensions_ui/src/extensions_ui.rs +++ b/crates/extensions_ui/src/extensions_ui.rs @@ -293,6 +293,7 @@ pub struct ExtensionsPage { workspace: WeakEntity, list: UniformListScrollHandle, is_fetching_extensions: bool, + fetch_failed: bool, filter: ExtensionFilter, remote_extension_entries: Vec, dev_extension_entries: Vec>, @@ -353,6 +354,7 @@ impl ExtensionsPage { workspace: workspace.weak_handle(), list: scroll_handle, is_fetching_extensions: false, + fetch_failed: false, filter: ExtensionFilter::All, dev_extension_entries: Vec::new(), filtered_remote_extension_indices: Vec::new(), @@ -479,6 +481,7 @@ impl ExtensionsPage { cx: &mut Context, ) { self.is_fetching_extensions = true; + self.fetch_failed = false; cx.notify(); let extension_store = ExtensionStore::global(cx); @@ -534,17 +537,31 @@ impl ExtensionsPage { }; let fetch_result = remote_extensions.await; - this.update(cx, |this, cx| { + + let result = this.update(cx, |this, cx| { cx.notify(); this.dev_extension_entries = dev_extensions; this.is_fetching_extensions = false; - this.remote_extension_entries = fetch_result?; - this.filter_extension_entries(cx); - if let Some(callback) = on_complete { - callback(this, cx); + + match fetch_result { + Ok(extensions) => { + this.fetch_failed = false; + this.remote_extension_entries = extensions; + this.filter_extension_entries(cx); + if let Some(callback) = on_complete { + callback(this, cx); + } + Ok(()) + } + Err(err) => { + this.fetch_failed = true; + this.filter_extension_entries(cx); + Err(err) + } } - anyhow::Ok(()) - })? + }); + + result? }) .detach_and_log_err(cx); } @@ -1277,7 +1294,9 @@ impl ExtensionsPage { let has_search = self.search_query(cx).is_some(); let message = if self.is_fetching_extensions { - "Loading extensions..." + "Loading extensions…" + } else if self.fetch_failed { + "Failed to load extensions. Please check your connection and try again." } else { match self.filter { ExtensionFilter::All => { @@ -1304,7 +1323,17 @@ impl ExtensionsPage { } }; - Label::new(message) + h_flex() + .py_4() + .gap_1p5() + .when(self.fetch_failed, |this| { + this.child( + Icon::new(IconName::Warning) + .size(IconSize::Small) + .color(Color::Warning), + ) + }) + .child(Label::new(message)) } fn update_settings( @@ -1673,9 +1702,7 @@ impl Render for ExtensionsPage { } if count == 0 { - this.py_4() - .child(self.render_empty_state(cx)) - .into_any_element() + this.child(self.render_empty_state(cx)).into_any_element() } else { let scroll_handle = self.list.clone(); this.child(