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