assistant_model_selector.rs

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