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}