agent_panel_onboarding_content.rs

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