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