From 0cf4dacd269e5fb4d73efc1e2e2dc23e57304c62 Mon Sep 17 00:00:00 2001 From: Finn Evers Date: Thu, 30 Jul 2026 16:55:00 +0200 Subject: [PATCH] extensions_ui: Move logic to render extension card details into `ExtensionCard` component (#61850) This PR reworks the extension card component to take care of most the rendering. It no longer implements `ParentElement` and instead takes care of rendering the details of the card now. This also allows us to finally render the list of features for dev extensions amongst some other cleanup whilst working with these. ## Why this change? This is in preparation for allowing to show extensions locally when the fetch fails based on the information available. Currently, this would require a lot of duplication and would be tedious to add. With this in, we can much more easily just construct an extension card with the upstream metadata missing, removing the need for duplication. Lastly, this also adds a component preview for extensions cards so we can play around more easily with other designs. Release Notes: - Installed dev extensions will now show the features they provide and will also respect feature filters. --- Cargo.lock | 2 +- crates/cloud_api_types/src/extension.rs | 11 + crates/extensions_ui/Cargo.toml | 2 +- crates/extensions_ui/src/components.rs | 3 +- .../src/components/extension_card.rs | 739 +++++++++++++++++- crates/extensions_ui/src/extensions_ui.rs | 638 +-------------- 6 files changed, 777 insertions(+), 618 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c06a7bc2cd..280bc530a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6432,6 +6432,7 @@ dependencies = [ "cloud_api_types", "collections", "command_palette_hooks", + "component", "db", "editor", "extension", @@ -6449,7 +6450,6 @@ dependencies = [ "semver", "serde", "settings", - "smallvec", "strum 0.27.2", "telemetry", "theme_settings", diff --git a/crates/cloud_api_types/src/extension.rs b/crates/cloud_api_types/src/extension.rs index 5bab3249d5..a62fc16ecf 100644 --- a/crates/cloud_api_types/src/extension.rs +++ b/crates/cloud_api_types/src/extension.rs @@ -52,6 +52,17 @@ pub enum ExtensionProvides { Snippets, } +impl ExtensionProvides { + pub fn is_deprecated(&self) -> bool { + matches!( + self, + ExtensionProvides::AgentServers + | ExtensionProvides::SlashCommands + | ExtensionProvides::IndexedDocsProviders + ) + } +} + #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)] pub struct ExtensionMetadata { pub id: Arc, diff --git a/crates/extensions_ui/Cargo.toml b/crates/extensions_ui/Cargo.toml index fbe4b1434f..617d53e0cd 100644 --- a/crates/extensions_ui/Cargo.toml +++ b/crates/extensions_ui/Cargo.toml @@ -15,6 +15,7 @@ path = "src/extensions_ui.rs" anyhow.workspace = true cloud_api_types.workspace = true command_palette_hooks.workspace = true +component.workspace = true collections.workspace = true db.workspace = true editor.workspace = true @@ -33,7 +34,6 @@ semver.workspace = true schemars.workspace = true serde.workspace = true settings.workspace = true -smallvec.workspace = true strum.workspace = true telemetry.workspace = true theme_settings.workspace = true diff --git a/crates/extensions_ui/src/components.rs b/crates/extensions_ui/src/components.rs index bf11abd679..92f9c3cdfe 100644 --- a/crates/extensions_ui/src/components.rs +++ b/crates/extensions_ui/src/components.rs @@ -1,3 +1,4 @@ mod extension_card; -pub use extension_card::*; +pub use extension_card::ExtensionCard; +pub(crate) use extension_card::{extension_provides_label, remote_extension_status}; diff --git a/crates/extensions_ui/src/components/extension_card.rs b/crates/extensions_ui/src/components/extension_card.rs index 524f90c7f0..22095a5d8d 100644 --- a/crates/extensions_ui/src/components/extension_card.rs +++ b/crates/extensions_ui/src/components/extension_card.rs @@ -1,35 +1,618 @@ -use gpui::{AnyElement, prelude::*}; -use smallvec::SmallVec; -use ui::prelude::*; +use std::{collections::BTreeSet, sync::Arc}; -#[derive(IntoElement)] -pub struct ExtensionCard { - overridden_by_dev_extension: bool, - children: SmallVec<[AnyElement; 2]>, +use cloud_api_types::{ExtensionApiManifest, ExtensionMetadata, ExtensionProvides}; +use extension::{ExtensionManifest, SchemaVersion}; +use extension_host::{ExtensionOperation, ExtensionStore}; +use gpui::{Anchor, ElementId, Entity, Point, SharedString, prelude::*}; +use num_format::{Locale, ToFormattedString}; +use release_channel::ReleaseChannel; +use ui::{Chip, ContextMenu, PopoverMenu, Tooltip, prelude::*}; + +type ContextMenuBuilder = Box< + dyn Fn(Arc, SharedString, &mut Window, &mut App) -> Option> + 'static, +>; +type ExtensionCardActions = [Option