1use std::sync::Arc;
2
3use ai_onboarding::{AgentPanelOnboardingCard, BulletItem};
4use client::zed_urls;
5use gpui::{AnyElement, App, IntoElement, RenderOnce, Window};
6use ui::{Divider, List, Tooltip, prelude::*};
7
8#[derive(IntoElement, RegisterComponent)]
9pub struct EndTrialUpsell {
10 dismiss_upsell: Arc<dyn Fn(&mut Window, &mut App)>,
11}
12
13impl EndTrialUpsell {
14 pub fn new(dismiss_upsell: Arc<dyn Fn(&mut Window, &mut App)>) -> Self {
15 Self { dismiss_upsell }
16 }
17}
18
19impl RenderOnce for EndTrialUpsell {
20 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
21 let pro_section = v_flex()
22 .gap_1()
23 .child(
24 h_flex()
25 .gap_2()
26 .child(
27 Label::new("Pro")
28 .size(LabelSize::Small)
29 .color(Color::Accent)
30 .buffer_font(cx),
31 )
32 .child(Divider::horizontal()),
33 )
34 .child(
35 List::new()
36 .child(BulletItem::new("500 prompts with Claude models"))
37 .child(BulletItem::new(
38 "Unlimited edit predictions with Zeta, our open-source model",
39 )),
40 )
41 .child(
42 Button::new("cta-button", "Upgrade to Zed Pro")
43 .full_width()
44 .style(ButtonStyle::Tinted(ui::TintColor::Accent))
45 .on_click(move |_, _window, cx| {
46 telemetry::event!("Upgrade To Pro Clicked", state = "end-of-trial");
47 cx.open_url(&zed_urls::upgrade_to_zed_pro_url(cx))
48 }),
49 );
50
51 let free_section = v_flex()
52 .mt_1p5()
53 .gap_1()
54 .child(
55 h_flex()
56 .gap_2()
57 .child(
58 Label::new("Free")
59 .size(LabelSize::Small)
60 .color(Color::Muted)
61 .buffer_font(cx),
62 )
63 .child(
64 Label::new("(Current Plan)")
65 .size(LabelSize::Small)
66 .color(Color::Custom(cx.theme().colors().text_muted.opacity(0.6)))
67 .buffer_font(cx),
68 )
69 .child(Divider::horizontal()),
70 )
71 .child(
72 List::new()
73 .child(BulletItem::new("50 prompts with the Claude models"))
74 .child(BulletItem::new("2,000 accepted edit predictions")),
75 );
76
77 AgentPanelOnboardingCard::new()
78 .child(Headline::new("Your Zed Pro Trial has expired"))
79 .child(
80 Label::new("You've been automatically reset to the Free plan.")
81 .color(Color::Muted)
82 .mb_2(),
83 )
84 .child(pro_section)
85 .child(free_section)
86 .child(
87 h_flex().absolute().top_4().right_4().child(
88 IconButton::new("dismiss_onboarding", IconName::Close)
89 .icon_size(IconSize::Small)
90 .tooltip(Tooltip::text("Dismiss"))
91 .on_click({
92 let callback = self.dismiss_upsell.clone();
93 move |_, window, cx| {
94 telemetry::event!("Banner Dismissed", source = "AI Onboarding");
95 callback(window, cx)
96 }
97 }),
98 ),
99 )
100 }
101}
102
103impl Component for EndTrialUpsell {
104 fn scope() -> ComponentScope {
105 ComponentScope::Agent
106 }
107
108 fn sort_name() -> &'static str {
109 "AgentEndTrialUpsell"
110 }
111
112 fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
113 Some(
114 v_flex()
115 .p_4()
116 .gap_4()
117 .child(EndTrialUpsell {
118 dismiss_upsell: Arc::new(|_, _| {}),
119 })
120 .into_any_element(),
121 )
122 }
123}