agent_panel_onboarding_content.rs

 1use std::sync::Arc;
 2
 3use client::{Client, UserStore};
 4use cloud_llm_client::{Plan, PlanV2};
 5use gpui::{Entity, IntoElement, ParentElement};
 6use language_model::{LanguageModelRegistry, ZED_CLOUD_PROVIDER_ID};
 7use ui::prelude::*;
 8
 9use crate::{AgentPanelOnboardingCard, ApiKeysWithoutProviders, ZedAiOnboarding};
10
11pub struct AgentPanelOnboarding {
12    user_store: Entity<UserStore>,
13    client: Arc<Client>,
14    has_configured_providers: bool,
15    continue_with_zed_ai: Arc<dyn Fn(&mut Window, &mut App)>,
16}
17
18impl AgentPanelOnboarding {
19    pub fn new(
20        user_store: Entity<UserStore>,
21        client: Arc<Client>,
22        continue_with_zed_ai: impl Fn(&mut Window, &mut App) + 'static,
23        cx: &mut Context<Self>,
24    ) -> Self {
25        cx.subscribe(
26            &LanguageModelRegistry::global(cx),
27            |this: &mut Self, _registry, event: &language_model::Event, cx| match event {
28                language_model::Event::ProviderStateChanged(_)
29                | language_model::Event::AddedProvider(_)
30                | language_model::Event::RemovedProvider(_)
31                | language_model::Event::ProvidersChanged => {
32                    this.has_configured_providers = Self::has_configured_providers(cx)
33                }
34                _ => {}
35            },
36        )
37        .detach();
38
39        Self {
40            user_store,
41            client,
42            has_configured_providers: Self::has_configured_providers(cx),
43            continue_with_zed_ai: Arc::new(continue_with_zed_ai),
44        }
45    }
46
47    fn has_configured_providers(cx: &App) -> bool {
48        LanguageModelRegistry::read_global(cx)
49            .visible_providers()
50            .iter()
51            .any(|provider| provider.is_authenticated(cx) && provider.id() != ZED_CLOUD_PROVIDER_ID)
52    }
53}
54
55impl Render for AgentPanelOnboarding {
56    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
57        let enrolled_in_trial = self
58            .user_store
59            .read(cx)
60            .plan()
61            .is_some_and(|plan| plan == Plan::V2(PlanV2::ZedProTrial));
62        let is_pro_user = self
63            .user_store
64            .read(cx)
65            .plan()
66            .is_some_and(|plan| plan == Plan::V2(PlanV2::ZedPro));
67
68        AgentPanelOnboardingCard::new()
69            .child(
70                ZedAiOnboarding::new(
71                    self.client.clone(),
72                    &self.user_store,
73                    self.continue_with_zed_ai.clone(),
74                    cx,
75                )
76                .with_dismiss({
77                    let callback = self.continue_with_zed_ai.clone();
78                    move |window, cx| callback(window, cx)
79                }),
80            )
81            .map(|this| {
82                if enrolled_in_trial || is_pro_user || self.has_configured_providers {
83                    this
84                } else {
85                    this.child(ApiKeysWithoutProviders::new())
86                }
87            })
88    }
89}