Skip to content

Commit 9667d78

Browse files
authored
extensions_ui: Improve error message when extensions fail to load (zed-industries#43197)
<img width="500" height="1902" alt="Screenshot 2025-11-20 at 6  12@2x" src="https://github.com/user-attachments/assets/daa5b020-17c8-4398-a64a-d691c566d6e7" /> 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.
1 parent 6adb0f4 commit 9667d78

File tree

1 file changed

+39
-12
lines changed

1 file changed

+39
-12
lines changed

crates/extensions_ui/src/extensions_ui.rs

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ pub struct ExtensionsPage {
293293
workspace: WeakEntity<Workspace>,
294294
list: UniformListScrollHandle,
295295
is_fetching_extensions: bool,
296+
fetch_failed: bool,
296297
filter: ExtensionFilter,
297298
remote_extension_entries: Vec<ExtensionMetadata>,
298299
dev_extension_entries: Vec<Arc<ExtensionManifest>>,
@@ -353,6 +354,7 @@ impl ExtensionsPage {
353354
workspace: workspace.weak_handle(),
354355
list: scroll_handle,
355356
is_fetching_extensions: false,
357+
fetch_failed: false,
356358
filter: ExtensionFilter::All,
357359
dev_extension_entries: Vec::new(),
358360
filtered_remote_extension_indices: Vec::new(),
@@ -479,6 +481,7 @@ impl ExtensionsPage {
479481
cx: &mut Context<Self>,
480482
) {
481483
self.is_fetching_extensions = true;
484+
self.fetch_failed = false;
482485
cx.notify();
483486

484487
let extension_store = ExtensionStore::global(cx);
@@ -534,17 +537,31 @@ impl ExtensionsPage {
534537
};
535538

536539
let fetch_result = remote_extensions.await;
537-
this.update(cx, |this, cx| {
540+
541+
let result = this.update(cx, |this, cx| {
538542
cx.notify();
539543
this.dev_extension_entries = dev_extensions;
540544
this.is_fetching_extensions = false;
541-
this.remote_extension_entries = fetch_result?;
542-
this.filter_extension_entries(cx);
543-
if let Some(callback) = on_complete {
544-
callback(this, cx);
545+
546+
match fetch_result {
547+
Ok(extensions) => {
548+
this.fetch_failed = false;
549+
this.remote_extension_entries = extensions;
550+
this.filter_extension_entries(cx);
551+
if let Some(callback) = on_complete {
552+
callback(this, cx);
553+
}
554+
Ok(())
555+
}
556+
Err(err) => {
557+
this.fetch_failed = true;
558+
this.filter_extension_entries(cx);
559+
Err(err)
560+
}
545561
}
546-
anyhow::Ok(())
547-
})?
562+
});
563+
564+
result?
548565
})
549566
.detach_and_log_err(cx);
550567
}
@@ -1277,7 +1294,9 @@ impl ExtensionsPage {
12771294
let has_search = self.search_query(cx).is_some();
12781295

12791296
let message = if self.is_fetching_extensions {
1280-
"Loading extensions..."
1297+
"Loading extensions…"
1298+
} else if self.fetch_failed {
1299+
"Failed to load extensions. Please check your connection and try again."
12811300
} else {
12821301
match self.filter {
12831302
ExtensionFilter::All => {
@@ -1304,7 +1323,17 @@ impl ExtensionsPage {
13041323
}
13051324
};
13061325

1307-
Label::new(message)
1326+
h_flex()
1327+
.py_4()
1328+
.gap_1p5()
1329+
.when(self.fetch_failed, |this| {
1330+
this.child(
1331+
Icon::new(IconName::Warning)
1332+
.size(IconSize::Small)
1333+
.color(Color::Warning),
1334+
)
1335+
})
1336+
.child(Label::new(message))
13081337
}
13091338

13101339
fn update_settings(
@@ -1673,9 +1702,7 @@ impl Render for ExtensionsPage {
16731702
}
16741703

16751704
if count == 0 {
1676-
this.py_4()
1677-
.child(self.render_empty_state(cx))
1678-
.into_any_element()
1705+
this.child(self.render_empty_state(cx)).into_any_element()
16791706
} else {
16801707
let scroll_handle = self.list.clone();
16811708
this.child(

0 commit comments

Comments
 (0)