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