assistant_model_selector.rs

 1use fs::Fs;
 2use gpui::{FocusHandle, View};
 3use language_model::LanguageModelRegistry;
 4use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
 5use settings::update_settings_file;
 6use std::sync::Arc;
 7use ui::{prelude::*, ButtonLike, PopoverMenuHandle, Tooltip};
 8
 9use crate::{assistant_settings::AssistantSettings, ToggleModelSelector};
10
11pub struct AssistantModelSelector {
12    selector: View<LanguageModelSelector>,
13    menu_handle: PopoverMenuHandle<LanguageModelSelector>,
14    focus_handle: FocusHandle,
15}
16
17impl AssistantModelSelector {
18    pub(crate) fn new(
19        fs: Arc<dyn Fs>,
20        menu_handle: PopoverMenuHandle<LanguageModelSelector>,
21        focus_handle: FocusHandle,
22        cx: &mut WindowContext,
23    ) -> Self {
24        Self {
25            selector: cx.new_view(|cx| {
26                let fs = fs.clone();
27                LanguageModelSelector::new(
28                    move |model, cx| {
29                        update_settings_file::<AssistantSettings>(
30                            fs.clone(),
31                            cx,
32                            move |settings, _cx| settings.set_model(model.clone()),
33                        );
34                    },
35                    cx,
36                )
37            }),
38            menu_handle,
39            focus_handle,
40        }
41    }
42}
43
44impl Render for AssistantModelSelector {
45    fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
46        let active_model = LanguageModelRegistry::read_global(cx).active_model();
47        let focus_handle = self.focus_handle.clone();
48
49        LanguageModelSelectorPopoverMenu::new(
50            self.selector.clone(),
51            ButtonLike::new("active-model")
52                .style(ButtonStyle::Subtle)
53                .child(
54                    h_flex()
55                        .gap_0p5()
56                        .child(
57                            div()
58                                .overflow_x_hidden()
59                                .flex_grow()
60                                .whitespace_nowrap()
61                                .child(match active_model {
62                                    Some(model) => h_flex()
63                                        .child(
64                                            Label::new(model.name().0)
65                                                .size(LabelSize::Small)
66                                                .color(Color::Muted),
67                                        )
68                                        .into_any_element(),
69                                    _ => Label::new("No model selected")
70                                        .size(LabelSize::Small)
71                                        .color(Color::Muted)
72                                        .into_any_element(),
73                                }),
74                        )
75                        .child(
76                            Icon::new(IconName::ChevronDown)
77                                .color(Color::Muted)
78                                .size(IconSize::XSmall),
79                        ),
80                )
81                .tooltip(move |cx| {
82                    Tooltip::for_action_in("Change Model", &ToggleModelSelector, &focus_handle, cx)
83                }),
84        )
85        .with_handle(self.menu_handle.clone())
86    }
87}