@@ -21,8 +21,8 @@ use settings::{LanguageModelProviderSetting, LanguageModelSelection};
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt as _};
use zed_actions::agent::{
- AddSelectionToThread, ConflictContent, OpenClaudeAgentOnboardingModal, ReauthenticateAgent,
- ResolveConflictedFilesWithAgent, ResolveConflictsWithAgent, ReviewBranchDiff,
+ AddSelectionToThread, ConflictContent, ReauthenticateAgent, ResolveConflictedFilesWithAgent,
+ ResolveConflictsWithAgent, ReviewBranchDiff,
};
use crate::{
@@ -40,7 +40,7 @@ use crate::{
};
use crate::{
DEFAULT_THREAD_TITLE,
- ui::{AcpOnboardingModal, ClaudeCodeOnboardingModal, HoldForDefault},
+ ui::{AcpOnboardingModal, HoldForDefault},
};
use crate::{ExpandMessageEditor, ThreadHistoryView};
use crate::{ManageProfiles, ThreadHistoryViewEvent};
@@ -245,11 +245,6 @@ pub fn init(cx: &mut App) {
.register_action(|workspace, _: &OpenAcpOnboardingModal, window, cx| {
AcpOnboardingModal::toggle(workspace, window, cx)
})
- .register_action(
- |workspace, _: &OpenClaudeAgentOnboardingModal, window, cx| {
- ClaudeCodeOnboardingModal::toggle(workspace, window, cx)
- },
- )
.register_action(|_workspace, _: &ResetOnboarding, window, cx| {
window.dispatch_action(workspace::RestoreBanner.boxed_clone(), cx);
window.refresh();
@@ -1,261 +0,0 @@
-use agent_servers::CLAUDE_AGENT_ID;
-use gpui::{
- ClickEvent, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable, MouseDownEvent, Render,
- linear_color_stop, linear_gradient,
-};
-use ui::{TintColor, Vector, VectorName, prelude::*};
-use workspace::{ModalView, Workspace};
-
-use crate::{Agent, agent_panel::AgentPanel};
-
-macro_rules! claude_agent_onboarding_event {
- ($name:expr) => {
- telemetry::event!($name, source = "ACP Claude Code Onboarding");
- };
- ($name:expr, $($key:ident $(= $value:expr)?),+ $(,)?) => {
- telemetry::event!($name, source = "ACP Claude Code Onboarding", $($key $(= $value)?),+);
- };
-}
-
-pub struct ClaudeCodeOnboardingModal {
- focus_handle: FocusHandle,
- workspace: Entity<Workspace>,
-}
-
-impl ClaudeCodeOnboardingModal {
- pub fn toggle(workspace: &mut Workspace, window: &mut Window, cx: &mut Context<Workspace>) {
- let workspace_entity = cx.entity();
- workspace.toggle_modal(window, cx, |_window, cx| Self {
- workspace: workspace_entity,
- focus_handle: cx.focus_handle(),
- });
- }
-
- fn open_panel(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut Context<Self>) {
- self.workspace.update(cx, |workspace, cx| {
- workspace.focus_panel::<AgentPanel>(window, cx);
-
- if let Some(panel) = workspace.panel::<AgentPanel>(cx) {
- panel.update(cx, |panel, cx| {
- panel.new_agent_thread(
- Agent::Custom {
- id: CLAUDE_AGENT_ID.into(),
- },
- window,
- cx,
- );
- });
- }
- });
-
- cx.emit(DismissEvent);
-
- claude_agent_onboarding_event!("Open Panel Clicked");
- }
-
- fn view_docs(&mut self, _: &ClickEvent, window: &mut Window, cx: &mut Context<Self>) {
- window.dispatch_action(Box::new(zed_actions::AcpRegistry), cx);
- cx.notify();
-
- claude_agent_onboarding_event!("Documentation Link Clicked");
- }
-
- fn cancel(&mut self, _: &menu::Cancel, _: &mut Window, cx: &mut Context<Self>) {
- cx.emit(DismissEvent);
- }
-}
-
-impl EventEmitter<DismissEvent> for ClaudeCodeOnboardingModal {}
-
-impl Focusable for ClaudeCodeOnboardingModal {
- fn focus_handle(&self, _cx: &App) -> FocusHandle {
- self.focus_handle.clone()
- }
-}
-
-impl ModalView for ClaudeCodeOnboardingModal {}
-
-impl Render for ClaudeCodeOnboardingModal {
- fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
- let illustration_element = |icon: IconName, label: Option<SharedString>, opacity: f32| {
- h_flex()
- .px_1()
- .py_0p5()
- .gap_1()
- .rounded_sm()
- .bg(cx.theme().colors().element_active.opacity(0.05))
- .border_1()
- .border_color(cx.theme().colors().border)
- .border_dashed()
- .child(
- Icon::new(icon)
- .size(IconSize::Small)
- .color(Color::Custom(cx.theme().colors().text_muted.opacity(0.15))),
- )
- .map(|this| {
- if let Some(label_text) = label {
- this.child(
- Label::new(label_text)
- .size(LabelSize::Small)
- .color(Color::Muted),
- )
- } else {
- this.child(
- div().w_16().h_1().rounded_full().bg(cx
- .theme()
- .colors()
- .element_active
- .opacity(0.6)),
- )
- }
- })
- .opacity(opacity)
- };
-
- let illustration = h_flex()
- .relative()
- .h(rems_from_px(126.))
- .bg(cx.theme().colors().editor_background)
- .border_b_1()
- .border_color(cx.theme().colors().border_variant)
- .justify_center()
- .gap_8()
- .rounded_t_md()
- .overflow_hidden()
- .child(
- div().absolute().inset_0().w(px(515.)).h(px(126.)).child(
- Vector::new(VectorName::AcpGrid, rems_from_px(515.), rems_from_px(126.))
- .color(ui::Color::Custom(cx.theme().colors().text.opacity(0.02))),
- ),
- )
- .child(div().absolute().inset_0().size_full().bg(linear_gradient(
- 0.,
- linear_color_stop(
- cx.theme().colors().elevated_surface_background.opacity(0.1),
- 0.9,
- ),
- linear_color_stop(
- cx.theme().colors().elevated_surface_background.opacity(0.),
- 0.,
- ),
- )))
- .child(
- div()
- .absolute()
- .inset_0()
- .size_full()
- .bg(gpui::black().opacity(0.15)),
- )
- .child(
- Vector::new(
- VectorName::AcpLogoSerif,
- rems_from_px(257.),
- rems_from_px(47.),
- )
- .color(ui::Color::Custom(cx.theme().colors().text.opacity(0.8))),
- )
- .child(
- v_flex()
- .gap_1p5()
- .child(illustration_element(IconName::Stop, None, 0.15))
- .child(illustration_element(
- IconName::AiGemini,
- Some("New Gemini CLI Thread".into()),
- 0.3,
- ))
- .child(
- h_flex()
- .pl_1()
- .pr_2()
- .py_0p5()
- .gap_1()
- .rounded_sm()
- .bg(cx.theme().colors().element_active.opacity(0.2))
- .border_1()
- .border_color(cx.theme().colors().border)
- .child(
- Icon::new(IconName::AiClaude)
- .size(IconSize::Small)
- .color(Color::Muted),
- )
- .child(Label::new("New Claude Agent Thread").size(LabelSize::Small)),
- )
- .child(illustration_element(
- IconName::Stop,
- Some("Your Agent Here".into()),
- 0.3,
- ))
- .child(illustration_element(IconName::Stop, None, 0.15)),
- );
-
- let heading = v_flex()
- .w_full()
- .gap_1()
- .child(
- Label::new("Beta Release")
- .size(LabelSize::Small)
- .color(Color::Muted),
- )
- .child(Headline::new("Claude Agent: Natively in Zed").size(HeadlineSize::Large));
-
- let copy = "Powered by the Agent Client Protocol, you can now run Claude Agent as\na first-class citizen in Zed's agent panel.";
-
- let open_panel_button = Button::new("open-panel", "Start with Claude Agent")
- .style(ButtonStyle::Tinted(TintColor::Accent))
- .full_width()
- .on_click(cx.listener(Self::open_panel));
-
- let docs_button = Button::new("add-other-agents", "Add Other Agents")
- .end_icon(
- Icon::new(IconName::ArrowUpRight)
- .size(IconSize::Indicator)
- .color(Color::Muted),
- )
- .full_width()
- .on_click(cx.listener(Self::view_docs));
-
- let close_button = h_flex().absolute().top_2().right_2().child(
- IconButton::new("cancel", IconName::Close).on_click(cx.listener(
- |_, _: &ClickEvent, _window, cx| {
- claude_agent_onboarding_event!("Canceled", trigger = "X click");
- cx.emit(DismissEvent);
- },
- )),
- );
-
- v_flex()
- .id("acp-onboarding")
- .key_context("AcpOnboardingModal")
- .relative()
- .w(rems(34.))
- .h_full()
- .elevation_3(cx)
- .track_focus(&self.focus_handle(cx))
- .overflow_hidden()
- .on_action(cx.listener(Self::cancel))
- .on_action(cx.listener(|_, _: &menu::Cancel, _window, cx| {
- claude_agent_onboarding_event!("Canceled", trigger = "Action");
- cx.emit(DismissEvent);
- }))
- .on_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, window, cx| {
- this.focus_handle.focus(window, cx);
- }))
- .child(illustration)
- .child(
- v_flex()
- .p_4()
- .gap_2()
- .child(heading)
- .child(Label::new(copy).color(Color::Muted))
- .child(
- v_flex()
- .w_full()
- .mt_2()
- .gap_1()
- .child(open_panel_button)
- .child(docs_button),
- ),
- )
- .child(close_button)
- }
-}
@@ -1,3 +1,7 @@
+// This module provides infrastructure for showing onboarding banners in the title bar.
+// It's currently not in use but is kept for future feature announcements.
+#![allow(dead_code)]
+
use gpui::{Action, Entity, Global, Render, SharedString};
use ui::{ButtonLike, Tooltip, prelude::*};
use util::ResultExt;
@@ -94,21 +98,21 @@ fn persist_dismissed(source: &str, cx: &mut App) {
}
pub fn restore_banner(cx: &mut App) {
- cx.defer(|cx| {
- cx.global::<BannerGlobal>()
- .entity
- .clone()
- .update(cx, |this, cx| {
+ if let Some(banner_global) = cx.try_global::<BannerGlobal>() {
+ let entity = banner_global.entity.clone();
+ cx.defer(move |cx| {
+ entity.update(cx, |this, cx| {
this.dismissed = false;
cx.notify();
});
- });
+ });
- let source = &cx.global::<BannerGlobal>().entity.read(cx).source;
- let dismissed_at = dismissed_at_key(source);
- let kvp = db::kvp::KeyValueStore::global(cx);
- cx.spawn(async move |_| kvp.delete_kvp(dismissed_at).await)
- .detach_and_log_err(cx);
+ let source = &cx.global::<BannerGlobal>().entity.read(cx).source;
+ let dismissed_at = dismissed_at_key(source);
+ let kvp = db::kvp::KeyValueStore::global(cx);
+ cx.spawn(async move |_| kvp.delete_kvp(dismissed_at).await)
+ .detach_and_log_err(cx);
+ }
}
impl Render for OnboardingBanner {
@@ -155,7 +155,7 @@ pub struct TitleBar {
multi_workspace: Option<WeakEntity<MultiWorkspace>>,
application_menu: Option<Entity<ApplicationMenu>>,
_subscriptions: Vec<Subscription>,
- banner: Entity<OnboardingBanner>,
+ banner: Option<Entity<OnboardingBanner>>,
update_version: Entity<UpdateVersion>,
screen_share_popover_handle: PopoverMenuHandle<ContextMenu>,
_diagnostics_subscription: Option<gpui::Subscription>,
@@ -246,7 +246,9 @@ impl Render for TitleBar {
children.push(self.render_collaborator_list(window, cx).into_any_element());
if title_bar_settings.show_onboarding_banner {
- children.push(self.banner.clone().into_any_element())
+ if let Some(banner) = &self.banner {
+ children.push(banner.clone().into_any_element())
+ }
}
let status = self.client.status();
@@ -385,19 +387,6 @@ impl TitleBar {
}));
}
- let banner = cx.new(|cx| {
- OnboardingBanner::new(
- "ACP Claude Code Onboarding",
- IconName::AiClaude,
- "Claude Agent",
- Some("Introducing:".into()),
- zed_actions::agent::OpenClaudeAgentOnboardingModal.boxed_clone(),
- cx,
- )
- // When updating this to a non-AI feature release, remove this line.
- .visible_when(|cx| !project::DisableAiSettings::get_global(cx).disable_ai)
- });
-
let update_version = cx.new(|cx| UpdateVersion::new(cx));
let platform_titlebar = cx.new(|cx| {
let mut titlebar = PlatformTitleBar::new(id, cx);
@@ -416,7 +405,7 @@ impl TitleBar {
user_store,
client,
_subscriptions: subscriptions,
- banner,
+ banner: None,
update_version,
screen_share_popover_handle: PopoverMenuHandle::default(),
_diagnostics_subscription: None,