agent_panel_onboarding_content.rs

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